diff --git a/数据库系统原理与实践/平时作业/第四次作业.tex b/数据库系统原理与实践/平时作业/第四次作业.tex new file mode 100644 index 0000000..e32e4fd --- /dev/null +++ b/数据库系统原理与实践/平时作业/第四次作业.tex @@ -0,0 +1,513 @@ +\documentclass[全部作业]{subfiles} +\input{mysubpreamble} + +\begin{document} +\setcounter{chapter}{3} +\chapter{第四次作业} +\begin{enumerate} + \item \choice[1]{关于视图的操作,下列哪条语句是正确的? + A + 可以使用 UPDATE 语句更新视图中的任意数据 + + B + 如果视图包含聚合函数,则该视图是不可(插入)更新的 + + C + 删除基表不会影响视图 + + D + 视图是只读的,不能对其执行 DELETE 操作 + + }{2} + \item \choice[1]{如果在 SQL 查询中使用右外连接(RIGHT OUTER JOIN),并且右表中某些记录没有与左表中的记录匹配,那么: + A + 右表中没有匹配的记录将被过滤掉 + + B + 右表中的记录将显示 NULL + + C + 右表中的记录将完整保留,左表没有匹配的记录会显示 NULL + + D + 查询将无法执行 + + }{3} + \item \choice[1]{给定以下 SQL 语句: + + CREATE VIEW employee_view AS + + SELECT id, name, department + + FROM employees + + WHERE department = 'Sales'; + + 该语句的作用是? + + + + A + 创建一个名为 employee_view 的物理表 + + B + 创建一个包含所有员工信息的物理表 + + C + 创建一个只包含销售部门员工的虚拟表 + + D + 修改现有的员工表以只包含销售部门员工}{3} + \item \choice[1]{以下哪个 SQL 语句可以删除视图? + A + DELETE VIEW view_name; + + B + DROP VIEW view_name; + + C + REMOVE VIEW view_name; + + D + ERASE VIEW view_name; + + }{2} + \item \choice[1]{假设有两张表,销售记录表 sales 和员工表 employees,要求查询出所有员工的姓名以及他们的销售记录,如果某个员工没有销售记录,销售记录应显示为 NULL。以下哪个 SQL 语句是正确的? + + A + \mint{SQL}|SELECT employees.employee_name, sales.sale_amount FROM employees LEFT OUTER JOIN sales ON employees.employee_id = sales.employee_id;| + + B + \mint{SQL}|SELECT employees.employee_name, sales.sale_amount FROM employees RIGHT OUTER JOIN sales ON employees.employee_id = sales.employee_id;| + + C + \mint{SQL}|SELECT employees.employee_name, sales.sale_amount FROM employees FULL OUTER JOIN sales ON employees.employee_id = sales.employee_id;| + + D + \mint{SQL}|SELECT employees.employee_name, sales.sale_amount FROM employees INNER JOIN sales ON employees.employee_id = sales.employee_id;| + }{1} + \questionandanswer[]{ + 上机题1:查询个人客户(individual)中“吕东”所有办理的业务信息。(输出:身份证号、姓名全名、客户编号、账户编号、开户行名称、可用余额、产品名称、产品类型名称); + +注意:客户全名可用CONCAT关键字,CONCAT(str1,str2,…)。 + }{} + { + \begin{minted}{SQL} +select ID_NUMBER 身份证号, + concat(LAST_NAME, FIRST_NAME) 姓名全名, + CUST_ID 客户编号, + ACCOUNT_ID 账户编号, + branch.NAME 开户行名称, + account.AVAIL_BALANCE 可用余额, + product.NAME 产品名称, + product_type.NAME 产品类型名称 +from individual + left join account using (CUST_ID) + left join branch on account.OPEN_BRANCH_ID = branch.BRANCH_ID + left join product using (PRODUCT_CD) + left join product_type using (PRODUCT_TYPE_CD) +where concat(LAST_NAME, FIRST_NAME) = "吕东"; + \end{minted} + \scriptsize\begin{csv} +,身份证号,姓名全名,客户编号,账户编号,开户行名称,可用余额,产品名称,产品类型名称 +1,450881196612220768,吕东,4,10,上海市总行,59934.1200,个人活期储蓄账户,存款 +2,450881196612220768,吕东,4,11,上海市总行,650600.0000,个人定期存款账户,存款 +3,450881196612220768,吕东,4,12,上海市总行,67800.0000,个人通知存款账户,存款 + \end{csv} + } + \questionandanswer[]{ + 上机题2:创建视图,查询客户(customer)表,列出所有客户的姓名全名、及其在单位的职位名称(title)(提示:对私客户职位为NULL)。(输出:全名,职位名称)。 + +注意:可使用CASE关键字处理对公对私客户,CASE [column_name] WHEN [value1] THEN [result1]... ELSE [default] END。 + }{} + { + \begin{minted}{SQL} +create view 视图1 as +select (case CUST_TYPE_CD + when 'B' then concat(officer.LAST_NAME, officer.FIRST_NAME) + else concat(individual.LAST_NAME, individual.FIRST_NAME) end) as 姓名全名, + (case CUST_TYPE_CD when 'B' then TITLE else NULL end) as 职位名称 +from customer + left join individual using (CUST_ID) + left join officer using (CUST_ID); + \end{minted} + \begin{csv} +,姓名全名,职位名称 +1,尤青, +2,许文强, +3,何婕, +4,吕东, +5,施珊珊, +6,张晓, +7,孔庆东, +8,曹方, +9,严匡, +10,华哨,校长 +11,金歌,董事长 +12,魏俊杰,董事长 +13,陶海桥,董事长 + \end{csv} + } + \questionandanswer[]{ + 上机题3:查询各个银行中余额最多的账户的客户信息。(输出:银行名称、姓名全名、账户余额) + +在account表中插入一条测试元组: + +insert into account values (30, 2000000, null, null, '2022-10-12', '正常', 5, 2, 15, 'CS'); + +提示:需要处理银行中余额最多的不止一个客户的情况。 + }{} + { + % 怎么感觉这么复杂,是不是哪里弄错了 + \begin{minted}{SQL} +insert into account +values (30, 2000000, null, null, '2022-10-12', '正常', 5, 2, 15, 'CS'); +select branch.NAME 银行名称, + (case CUST_TYPE_CD + when 'B' then concat(officer.LAST_NAME, officer.FIRST_NAME) + else concat(individual.LAST_NAME, individual.FIRST_NAME) end) 姓名全名, + account.AVAIL_BALANCE 账户余额 +from (select account.ACCOUNT_ID, OPEN_BRANCH_ID, AVAIL_BALANCE, max_avail_balance + from account + join + (select OPEN_BRANCH_ID, max(AVAIL_BALANCE) as max_avail_balance + from account + group by OPEN_BRANCH_ID) as b using (OPEN_BRANCH_ID) + where AVAIL_BALANCE = max_avail_balance) as abAI + left join branch on BRANCH_ID = OPEN_BRANCH_ID + left join account using (ACCOUNT_ID) + left join individual using (CUST_ID) + left join officer using (CUST_ID) + left join customer using (CUST_ID); + \end{minted} + \begin{csv} +,银行名称,姓名全名,账户余额 +1,上海市总行,张晓,3330000.0000 +2,建国支行,许文强,2000000.0000 +3,建国支行,施珊珊,2000000.0000 +4,南京分行,何婕,650000.0000 +5,杭州分行,施珊珊,340023.0000 + \end{csv} + } + \questionandanswer[]{ + 上机题4:查询所有同时办理了产品编号为“CS”和“RS”的个人客户(individual表)的身份证号(ID_NUMBER)和姓名全名。(输出:ID_NUMBER,全名)。 + +要求:使用NOT EXISTS进行包含关系查询。 + }{} + { + \begin{minted}{SQL} +select individual.ID_NUMBER 身份证号, concat(individual.LAST_NAME, individual.FIRST_NAME) 姓名全名 +from individual +where not exists(select * + from account + where PRODUCT_CD != 'CS' and PRODUCT_CD != 'RS' and account.CUST_ID = individual.CUST_ID); + \end{minted} + \begin{csv} +,身份证号,姓名全名 +1,41032619780815564X,许文强 +2,370900196802069281,何婕 +3,320623197108259227,施珊珊 +4,321111197703197600,孔庆东 + \end{csv} + } + + \questionandanswer[]{ + 上机题5:查询所有不在2013年(例如在2011、2019年等)有交易记录的账户编号(ACCOUNT_ID)。(输出:账户编号) + +要求:需要用外连接来写该查询语句; + +注意:某些账户可能在2011、2013年都有交易记录,但只要在2013年有一条交易记录的账户都会被排除在结果集之外。 + }{} + {\kaishu + 这题表述不清啊,是指“在2011、2019年等有交易记录”呢?还是“在2013年没有交易记录”呢?还是两个条件都要? + + 那么暂且认为是“在2013年没有交易记录”吧,也就是这样: + + \begin{csv} +,2013年有交易记录,2013年无交易记录 +其他年有交易记录,不要,要 +其他年无交易记录,不要,要 + \end{csv} + \begin{minted}{SQL} +select ACCOUNT_ID +from account + left join (select * + from acc_transaction + where year(TXN_DATE) != 2013) as not2013 using (ACCOUNT_ID) +where TXN_DATE is not null; + \end{minted} + \begin{csv} +,ACCOUNT_ID +1,4 +2,5 +3,18 +4,19 +5,21 +6,28 +7,10 +8,17 +9,13 +10,29 +11,27 +12,3 +13,23 +14,12 +15,22 +16,15 +17,28 + \end{csv} + } + \questionandanswer[]{ + 教材3.11: 使用大学University数据库模式,请用SQL写出如下查询。 + +a.找出至少选修了一门Comp. Sci.课程的每名学生的ID和姓名,保证结果中没有重复的姓名。 + +b.找出没有选修2017年之前开设的任何课程的每名学生的ID和姓名。 + +c.找出每个系的教师的最高工资值。可以假设每个系至少有一位教师。 + +d.从前述查询所计算出的每个系的最高工资中选出所有系中的最低值。 + }{} + {\kaishu + \begin{enumerate} + \item \begin{minted}{SQL} + select distinct ID, name + from course + left join takes using (course_id) + left join student using (ID) + left join department on course.dept_name = department.dept_name + where course.dept_name = "Comp. Sci."; + \end{minted} + \item \begin{minted}{SQL} + select ID, name + from student + where not exists(select * + from takes + where takes.ID = student.ID and year < 2017); + \end{minted} + \item \begin{minted}{SQL} + select dept_name, max(salary) + from instructor + group by dept_name; + \end{minted} + \item \begin{minted}{SQL} + with a as (select dept_name, max(salary) max_salary + from instructor + group by dept_name) + select * + from a + where max_salary = (select min(max_salary) + from a); + \end{minted} + \end{enumerate} + } + \begin{figure} + \centering + \includegraphics[width=1\linewidth]{imgs/2024-10-19-09-53-31.png} + \caption{大学数据库的模式图} + \end{figure} + \begin{verification} + 教材的前言中介绍了官网:\url{https://db-book.com/},官网上可以下载示例数据:\url{https://db-book.com/university-lab-dir/sample_tables-dir/index.html},于是可以验证了。 + \begin{minted}{SQL} +select distinct ID, name +from course + left join takes using (course_id) + left join student using (ID) + left join department on course.dept_name = department.dept_name +where course.dept_name = "Comp. Sci."; + +select ID, name +from student +where not exists(select * + from takes + where takes.ID = student.ID + and year < 2017); + +select dept_name, max(salary) +from instructor +group by dept_name; + +with a as (select dept_name, max(salary) max_salary + from instructor + group by dept_name) +select * +from a +where max_salary = (select min(max_salary) + from a); + \end{minted} + + \begin{csv} +,ID,name +1,00128,Zhang +2,12345,Shankar +3,45678,Levy +4,54321,Williams +5,76543,Brown +6,98765,Bourikas + \end{csv} + + \begin{csv} +,ID,name +1,00128,Zhang +2,12345,Shankar +3,19991,Brandt +4,23121,Chavez +5,44553,Peltier +6,45678,Levy +7,54321,Williams +8,55739,Sanchez +9,70557,Snow +10,76543,Brown +11,76653,Aoi +12,98765,Bourikas +13,98988,Tanaka + \end{csv} + + \begin{csv} +,dept_name,max(salary) +1,Biology,72000.00 +2,Comp. Sci.,92000.00 +3,Elec. Eng.,80000.00 +4,Finance,90000.00 +5,History,62000.00 +6,Music,40000.00 +7,Physics,95000.00 + \end{csv} + + \begin{csv} +,dept_name,max_salary +1,Music,40000.00 + \end{csv} + \end{verification} + + \questionandanswer[]{ + 教材3.16:考虑图 \ref{fig:3-19} 中的雇员数据库,其中主码被加了下划线。请给出下面每个查询的SQL表达式 + +a.找出每位这样的雇员的ID和姓名:该雇员所居住的城市与其工作的公司所在城市一样。 + +b.找出所居住的城市和街道与其经理相同的每位雇员的ID和姓名。 + +c.找出工资高于其所在公司所有雇员平均工资的每位雇员的ID和姓名。 + +d.找出工资总和最小的公司。 + }{} + \begin{figure} + \centering + \includegraphics[width=0.5\linewidth]{imgs/2024-10-19-14-28-27.png} + \caption{雇员数据库}\label{fig:3-19} + \end{figure} + + {\kaishu + \begin{enumerate} + \item \begin{minted}{SQL} +select ID, person_name +from employee + join works using (ID) + join company using (company_name) +where employee.city = company.city; + \end{minted} + + \item \begin{minted}{SQL} +select subordinate.ID, subordinate.person_name +from manages + join employee as subordinate using (ID) + join employee as superior on manages.manager_id = superior.ID +where superior.street = subordinate.street + and superior.city = subordinate.city; + \end{minted} + + \item \begin{minted}{SQL} +-- 这里假设employee.ID <--> works.ID 是一一对应的关系 +select ID, person_name +from works + join (select company_name, avg(salary) as avg_salary + from works + group by company_name) as a using (company_name) + join employee using (ID) +where works.salary > a.avg_salary; + \end{minted} + + \item \begin{minted}{SQL} +with a as (select company_name, sum(salary) as sum_salary + from company + join works using (company_name) + group by company_name) +select company_name +from a +where sum_salary = (select min(sum_salary) from a); + \end{minted} + \end{enumerate} + } + \questionandanswer[]{ + 教材3.17:考虑图 \ref{fig:3-19} 中的雇员数据库。请给出下面每个查询的SQL表达式。 + +a.为“First Bank Corporation"的所有雇员增长10\%的工资。 + +b.为“First Bank Corporation”的所有经理增长10\%的工资。 + +c.删除“Small Bank Corporation"的雇员在works关系中的所有元组。 + }{} + {\kaishu + \begin{enumerate} + \item \begin{minted}{SQL} +update works +set salary = salary * 1.1 +where company_name = "First Bank Corporation"; + \end{minted} + \item \begin{minted}{SQL} +update works +join manages on works.ID = manages.manager_id +set salary = salary * 1.1 +where company_name = "First Bank Corporation"; + \end{minted} + \item \begin{minted}{SQL} +delete from works +where company_name = "Small Bank Corporation"; + \end{minted} + \end{enumerate} + } + \questionandanswer[]{ + 教材3.18:请给出图 \ref{fig:3-19} 的雇员数据库的SQL模式定义。为每个属性选择合适的域,并为每个关系模式选择合适的主码。引人任何合理的外码约束。 + }{} + {\kaishu + \begin{minted}{SQL} +create table employee +( + ID varchar(10) primary key, + person_name varchar(100), + street varchar(100), + city varchar(100) +); + +create table works +( + ID varchar(10) primary key, + company_name varchar(100), + salary decimal(8, 2) +); + +create table company +( + company_name varchar(100) primary key, + city varchar(100) +); + +create table manages +( + ID varchar(10) primary key, + manager_id varchar(10) +); + + +alter table works + add (foreign key (company_name) references company (company_name), + foreign key (ID) references employee (ID)); + +alter table manages + add (foreign key (manager_id) references employee (ID), + foreign key (ID) references employee (ID)); + \end{minted} + } +\end{enumerate} + +\end{document} \ No newline at end of file