FChao
发布于 2026-05-14 / 26 阅读
0
0

数据库系统工程师⑱:案例题3-SQL应用

2025真题:

【说明】

某银行数据库系统的部分数据库关系模式如下:

支行:BRANCH(Bno,Bname, address),各属性分别表示支行编号、名称、地址;

客户:CUSTOMER(CID,Cname, tel)各属性分别表示客户编号、姓名、电话;

贷款:LOAN (Lno, Bno, CID, amount, Ldatetime),各属性分别表示贷款编号、支行编号、客户编号、

贷款金额、贷款时间;

还款:PAYMENT(Pno,Lno,num,Pdatetme),各属性分别表示还款编号、贷款编号、还款金额、还款时间。

有关关系模式的说明如下:

(1)实下划线标出的属性是表的主键。

(2)每位客户只存储一个电话号码。

(3)每位客户在同一个支行可以有多笔贷款。

(4)每笔贷款可以分多次还清,即每笔贷款可以有多条还款记录。每次的还款金额最少为100。

(5)贷款时间和还款时间不能为空。

根据以上描述,将SOL语句的空缺部分补充完整

1. (4分)假设其它表已经创建,请将下面创建还款表PAYMENT的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。

CREATE TABLE PAYMENT(

Pno CHAR(6)(a),

Lno CHAR(5) (b),

num DECIMAL(10,2) (c),

Pdatetime DATETIME(d) )

a:PRIMARY KEY

b:references LOAN(Lno)

c:CHECK(num>=100)

d:NOT NULL

2.(3分)在贷款表LOAN中新增一条记录,各属性值依次为:L0005,B010,C0008,12000,getdatetime(),其中getdatetime()为获取当前系统时间的函数。此功能可以由下面的SQL语句实现,请补全。(e)_LOAN_(f)_('L0005,'B010,C0008,12000, (g) );

e:insert into

f:values

g:getdatetime()

3. (4分)查询在’A支行‘有贷款的所有客户的姓名和电话。此功能由下面的SQL语句实现,请补全。

SELECT Cname,tel

FROM LOAN,CUSTOMER,(h)

(i) LOAN.CID=CUSTOMER.CID

AND __(j)__

AND__(k)__

注意要用上题目提供的提示条件,首先可以确定Bname=‘A支行’

其次发现三表两两连接缺少了连接符号

h:BRANCH

i:WHERE

j:LOAN.Bno=BRANCH.Bno # k 和 j 答案顺序无要求可以颠倒

k:Bname=‘A支行’

4. (4分)查询在该银行贷款总金额超过10万元的客户姓名、电话以及他们各自的贷款总金额。某大语言模型提供了实现该查询功能的SQL语句如下所示。此语句存在3个错误,其中1个错误由例子给出并改正,请找出其余2个错误并改正。

SELECT Cname As 客户姓名,tel As 电话号码,SUM(amount) As 贷款总金额

FROM LOAN,CUSTOMER

WHERE LOAN.CID=CUSTOMER.CID

GROUP BY CID HAVING amount>100000;

例:

错误:SELECT子句的Cname 改正:MIN(Cname)

错误:SELECT子句的tel 改正:MIN(tel)

错误:HAVING子句的amount 改正:SUM(amount)

高频考点:SELECT中的非聚合列,必须出现在GROUP BY中。

这里用CID group by,那么上面的select必须全部是聚合的。

(为什么不是GROUP BY CNAME?因为客户的姓名可能重名,其次,group by后面并不一定是要select中出现,因为select实际上是最后去选要显示哪些列,只要在from里面就可以了)

这里取MIN是什么意思?我们只按CID分组之后,一行里面只有一个聚合了的amount,但是有好多重复的姓名和电话,这里强行只取其中一个,强行变成聚合列。用MAX也是可以的。

我们还可以

SELECT
    Cname AS 客户姓名,
    tel AS 电话号码,
    SUM(amount) AS 贷款总金额
FROM LOAN, CUSTOMER
WHERE LOAN.CID = CUSTOMER.CID
GROUP BY CID, Cname, tel
HAVING SUM(amount) > 100000;

HAVING SUM(amount) > 100000;

首先,我们要判断的是总金额。其次,amount既然不在group里面,我们不可以用处理分组的HAVING去处理它。

1.

【说明】
某教务管理系统的部分数据库关系模式如下:
学生:STUDENT(Sno,Sname,Ssex,Sage,Sdept),各属性分别表示学号、姓名、性别、年龄、所在系名;
课程:COURSE(Cno,Cname,Cpno,Ceredit),各属性分别表示课程号、课程名、选修课的课程号、学分;
选课:SC(Sno,Cno,Grade),各属性分别表示学号、课程号、成绩。
有关关系模式的说明如下:
(1)下划线标出的属性是表的主键。
(2)课程名取值唯一。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。

完整性约束/参照性约束

【问题1】(3分)

请将下面创建课程表COURSE的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束以及其他完整性约束。

CREATE TABLE COURSE(
Cno CHAR(4)PRIMARY KEY,
Cname CHAR(30) (a),
Cpno CHAR(4) REFERENCES (b) ((c))
Ccredit INT);

课程:COURSE(Cno,Cname,Cpno,Ceredit)

实体完整性:保证表中的每一行数据是唯一的,已由主键(Primary Key)实现

参照完整性:保证表间关系正确,外键值必须在主表存在或为 NULL。

Cname是课程名,题目提到课程名唯一,因此Cname加上UNIQUE

Cpno 是外键,它参照的是同一个表 COURSE 的主键 Cno。

因此(b) COURSE (c) Cno


【问题2】(4分)
有一门课程号为“C036的新开课要求所有学生选修。该课的基本信息已经录入课程表COURSE中,现需在选课表SC中插入该课的选课记录。实现此功能的SQL语句如下,请补全。

(d) INTO SC(Sno, (e))
SELECT Sno, (f)
FROM (g );

选课:SC(Sno,Cno,Grade) 学号、课程号、成绩

插入语法:

INSERT INTO 表名(列1, 列2) SELECT 列1, 列2[或常量] FROM 源表

插入选课记录,d填写INSERT

这道题只操作其中的两列,选课和成绩无关,另一列应当是课程号

e填写Cno

(f)处填入'C036'是因为该SQL语句需要为所有学生插入固定课程号" C036"的选课记录。此处'C036'是常量值,直接指定课程号,并非从STUDENT表中读取。

学号的信息只能是从学生表中来,因此G填写STUDENT

JOIN连接查询

【问题3】(4分)
查询每一门课程的间接选修(选修课的选修课),要求输出课程号和间接选修课的课程号。即使某门课程没有选修课,也需要输出,不过其间接选修课为空。此功能由下面的SQL语句实现,请补全。

SELECT K1.Cno, (h)
FROM COURSE K1 (i) OUTER JOIN COURSE K2 (j) ((k));

从两个COURSE表的别名K1,K2中连接查询,在select处首先要选择两张表。K1.Cno是某个课程号,K2我们需要某个课程号的选修课程号Cpno。

(h) K2.Cpno

连接查询的语法:FROM 主表 [连接方式] JOIN 被关联表 ON 条件

(i) LEFT (j) ON

K1取的是选修课的课程号,K2取的是选修课的选修课的课程号,题目已经写出以K1为主表,即使某门课程没有选修课,也需要输出,那么就是以保留左边的左连接。

假如有A/B两张表,我们FROM A RIGHT JOIN B,和FROM B LEFT JOIN A,这两种写法在查询结果上是完全等价的。

判断连接条件:K1的选修课的课程号,就是K2他自己的课程号

K1.Cpno = K2.Cno

注意不要写反了变成k1.cno=k2.Cpno,那就反过来K2的选修课是K1了

嵌套查询/where not exist

【问题4】(4分)
查询选修了课程表中已有全部课程的学生,要求输出学号和姓名。此功能由下面的SQL语句实现,请补全。

SELECT Sno,Sname FROM STUDENT
WHERE NOT EXISTS
(SELECT * FROM (l)
WHERE (m)
(SELECT * FROM (n)
WHERE(o) ));

答案:

我要找的学生:
    ↓
不存在这样一门课:
    这门课,这个学生没有选

SELECT Sno, Sname FROM STUDENT

WHERE NOT EXISTS ( #3.找不到任何一门课这学生没选,则成立select学生

SELECT * FROM COURSE

WHERE NOT EXISTS ( #2.找不到的时候,not exists成立,筛出了没选的课

SELECT * FROM SC #1.最内层查询:找出所有【有人选的课】

WHERE SC.Cno = COURSE.Cno

AND SC.Sno = STUDENT.Sno

)

);

结构:select * from 某主表 where not exist(某嵌套查询)

遍历主表的每一行,并对当前主表的行执行嵌套查询,嵌套查询的内容

找不到 → 真 → 保留;找得到 → 假 → 丢弃

最内层:SELECT * FROM SC WHERE SC.Cno = 所有课程中的某个 AND SC.Sno = 所有学生中的某个

选课:SC(Sno,Cno,Grade)

课程号Sno匹配课程表COURSE,学号Cno匹配学生表STUDENT

把某个课程有某个学生选了的所有记录都找出来了

当最内层这个select,通过外层给它的SC.Cno和SC.Sno查不到,不成立的时候,说明某个课没有学生选,NOT EXISTS成真,这个没人选的COURSE被保存下来。SELECT * FROM COURSE

SELECT Sno, Sname FROM STUDENT WHERE NOT EXISTS ( 遍历了所有的课程,如果任何一门课都找不到没选的,条件成立,把这个学生筛选出来 )

2.

【说明】
某工程项目管理系统的部分数据库关系模式如下:
项目:PROJECT(Jno,Jname,City,Date ),各属性分别表示项目代码、项目名称、项目所在城市和项目开始日期;
零件:PART (Pno,Pname,Color,Sno,Stock),各属性分别表示零件代码、零件名称、零件颜色、零件所在仓库代码及库存量;
供应情况:PJ(Pno,Jno,Qty ),各属性分别表示零件代码、项目代码、使用量;
仓库:STORE(Sno,Sname,Address ),各属性分别表示仓库代码、仓库名称、仓库地址。
有关上述关系模式的说明如下:
(1)下划线标出的属性是表的主键。
(2)零件表的属性Sno参照了仓库表的主码。一种零件只存放在一个仓库,库存量最低为0。
(3)供应情况表的属性Pno和Jno分别参照了零件表和项目表的主码。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。

【问题1】(4分)
请将下面创建零件表PART的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。

CREATE (a) PART(
Pno CHAR(10) (b)
Pname CHAR(20),
Color CHAR(4),
Sno CHAR(4) REFERENCES (c) (Sno)
Stock INT (d) );

零件:PART (Pno,Pname,Color,Sno,Stock)

零件表的属性Sno参照了仓库表的主码。一种零件只存放在一个仓库,库存量最低为0。

(a) TABLE:SQL 创建表的完整关键字为 CREATE TABLE。

(b) PRIMARY KEY:Pno 是零件表的主键,需定义实体完整性约束。

(c) STORE:Sno 是外键,参照仓库表的主码 Sno,因此写表名 STORE。

用户定义完整性约束

(d) CHECK(Stock >= 0):题目规定“库存量最低为0”,需用 CHECK 约束限制 Stock 的取值范围。

列名 数据类型 [可选 CONSTRAINT 约束名] CHECK (列名 条件表达式)

视图

视图定义从 CREATE VIEW 名称 AS ... 开始,到第一个分号结束。后续要使用直接以后直接 SELECT * FROM 视图。

【问题2】(3分)
创建视图PARTUSED,给出在项目中已使用零件的代码和使用量。此视图的创建语句如下,请补全。

CREATE VIEW PARTUSED AS SELECT Pno, (e) AS Usage FROM PJ (f) BY (g);

供应情况:PJ(Pno,Jno,Qty ),各属性分别表示零件代码、项目代码、使用量;在供应情况表 PJ 中,同一种零件可能被多个不同的项目使用,所以它的使用量 Qty 是分散在多行记录中的。

Pno (零件代码)Jno (项目代码)Qty (使用量)
P01	J01	10
P01	J02	15
P02	J01	8

(e) SUM(Qty):需要统计每个零件的总使用量,因此对 Qty 求和,并用别名 Usage 表示。

(f) GROUP:看到select末尾有 BY 要联想到组成 GROUP BY 子句。

(g) Pno:

题目说给出在项目中已使用零件的代码和使用量,如果分组,应该是按零件代码分组,统计出每种零件在所有项目中的使用总量。
【问题3】(4分)
在视图PARTUSED的基础上,查询所有零件的信息要求输出每种零件的零件代码、零件名、零件颜色和零件总量(使用量与库存量之和 ),查询结果按照零件总量降序排列。此功能由下面的SQL语句实现,请补全。

SELECT Pno,Pname, Color, (h) AS Total
FROM PART,PART_USED
WHERE PART.Pno=PART_USED.Pno
(i)
SELECT Pno,Pname,Color,Stock AS Total
FROM PART
WHERE Pno (j)
( SELECT DISTINCT Pno FROM PJ )
ORDER BY Total (k)

零件:PART (Pno,Pname,Color,Sno,Stock),各属性分别表示零件代码、零件名称、零件颜色、零件所在仓库代码及库存量;

(h)要表示使用量与库存量之和 ,但是注意这里不会是聚合函数,因为SQL中的聚合函数都是针对某列的多个行计算。而这里是将选出的单独两值进行相加。都是数值类型直接相加即可。

(h) PART_USED.Usage + PART.Stock

(k) DESC:ORDER BY Total DESC 表示按零件总量降序排列。

UNION/DISTINCT

把多个查询结果上下堆叠成一张表,UNION 是纵向连接(行与行拼接),JOIN 是横向连接(列与列拼接)。

对比题目发现,上下两端查询的列,列数/含义和数据类型完全一致。应当使用UNION。

为什么?我们在视图PART_USED中只定义了查询使用过的零件。为了补上丢失的“未使用零件”,需要:找出那些 Pno 在 PART 表中存在,但不在 PJ 表中的零件。

SELECT DISTINCT Pno FROM PJ;

将Pno列的元素去重地选出,每个只出现一次

WHERE Pno NOT IN (SELECT DISTINCT Pno FROM PJ)

选出的零件都是之前没在PJ中出现过的

转移表记录

【问题4】(4分)
由于某种原因,要拆除代码为'A006'的仓库,该仓库中的零件转入'A002'仓库存放。据此更新数据库的功能由下面的SQL语句实现,请补全。

UPDATE (l) SET (m) WHERE Sno='A006';
(n) FROM (o) WHERE Sno='A006'

仓库:STORE(Sno,Sname,Address ),各属性分别表示仓库代码、仓库名称、仓库地址。

零件:PART (Pno,Pname,Color,Sno,Stock),各属性分别表示零件代码、零件名称、零件颜色、零件所在仓库代码及库存量;

UPDATE PART SET Sno = 'A002' WHERE Sno = 'A006';
DELETE FROM STORE WHERE Sno = 'A006';

(l) PART:要转移零件,需修改零件所在的仓库代码,更新的是 PART 表。

(m) Sno = 'A002':将零件的仓库代码从 'A006' 改为 'A002'。

看到分号,第一个sql语句已经结束。下一步还是A006?那只能是删除原来的了。

(n) DELETE:拆除仓库意味着从仓库表中删除该仓库记录。

(o) STORE:删除的是 STORE 表中 Sno = 'A006' 的仓库记录。

3.

【说明】
某订单管理系统的部分数据库关系模式如下:
客户:CUSTOMERS(Cno, Cname, Cage, Csex),各属性分别表示客户编号、客户姓名、年龄和性别;
商品:GOODS(Gno, Gname, Gprice, Gorigin),各属性分别表示商品编号、商品名称、单价和产地;
订单:ORDERS(Ono, Cno, Gno, Oprice, Onumber),各属性分别表示订单编号、客户编号、商品编号、顾客购买商品的单价和数量。
有关关系模式的说明如下:
(1)下划线标出的属性是表的主键。
(2)商品表中的Gprice是商品的当前价格,可能会发生变动;订单表中的Oprice是订单成交时的商品单价。
(3)一个订单只包含一位顾客购买的一种商品;其商品数量至少1件,最多99件。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。

【问题1】(3分)
请将下面创建订单表的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。

CREATE TABLE ORDERS (
Ono CHAR(20) PRIMARY KEY,
Cno CHAR(10) (a),
Gno CHAR(15) (b),
Oprice NUMERIC(7,2),
Onumber SMALLINT (c) );

订单:ORDERS(Ono, Cno, Gno, Oprice, Onumber),各属性分别表示订单编号、客户编号、商品编号、顾客购买商品的单价和数量。

注意观察!Cno和Gno都是其他表的主键,且题目要求定义参照完整性约束

references customers(Cno)

references goods(Gno)

对于大于且小于的商品数量,使用AND符合连接

CHECK(Onumber >= 1 AND Onumber <= 99)

【问题2】(5分)
查询所有订单的详细情况,要求输出订单号(Ono)、 客户姓名(Cname)、 商品名称(Gname)、单价(Oprice)、数量(Onumber)和金额(Oamount), 查询结果按照金额从大到小排列。此功能由下面的SQL语句实现,请补全。

SELECT Ono, Cname, Gname, Oprice, Onumber,(d) AS Oamount
FROM CUSTOMERS, ORDERS, GOODS
WHERE (e)
AND (f)
(g) BY (h) ;

(d) Oprice * Onumber:订单金额 = 单价 × 数量,又取了别名 Oamount。

这里要注意到这次的select选择了三张表,后续子句Where...and应当是三张表两两连接。

(e) ORDERS.Cno = CUSTOMERS.Cno:关联订单表和客户表。

(f) ORDERS.Gno = GOODS.Gno:关联订单表和商品表。((e)和(f)顺序可互换)

(g) ORDER:排序子句关键字。

写排序的时候不要忘了,还需要BY 排序列名

(h) Oamount DESC:按金额从大到小(降序)排列。

【问题3】(5分)
创建已售商品信息视图,给出已售商品的编号(Gno)、名称(Gname)、订单个数(Onum)及平均每单的商品数量(GAnum)。此视图的创建语句如下,请补全。

CREATE (i ) GOODS_SOLD AS
SELECT ORDERS. Gno AS Gno, MIN (GOODS. Gname) AS Gname,
(j) AS Onum, (k) AS GAnum .
FROM ORDERS, GOODS
WHERE ORDERS.Gno = GOODS . Gno .
(l ) BY_ (m);

注意题目,创建的是视图而表!!

(i) VIEW:创建视图的关键字。

COUNT/AVG聚合函数

(j) COUNT(*):统计每种商品的订单个数(每个订单只包含一种商品,所以计算订单表的行数即可)。

(k) AVG(Onumber):计算该商品平均每单的购买数量。

(l) GROUP:又考察了一次视图末尾分组。因为同时select了聚合和非聚合列。

(m) ORDERS.Gno:按商品编号分组。这里要注意需求是商品信息,编号是唯一的主键。按名称会导致信息丢失。

EXCEPT

它把两个查询结果当成完整的集合,然后进行差集运算。这要求上下两个查询的列数和数据类型必须一致。

A EXCEPT B = 在 A 中存在,但在 B 中不存在的记录
B EXCEPT A = 在 B 中存在,但在 A 中不存在的记录

【问题4】(2分)
查询未售出商品的编号和名称。此功能由下面的SQL语句实现,请补全。

SELECT Gno, Gname
FROM (n)
(o)
SELECT Gno , Gname
FROM GOODS_SOLD;

(n) GOODS:从商品表中选取所有商品的编号和名称。

(o) EXCEPT:用集合差操作,减去已售出商品视图 GOODS_SOLD 中存在的商品,剩下的就是未售出商品。EXCEPT 会自动去重。

4.

【说明】

某竞赛管理系统的部分数据库关系模式如下:

选手: PLAYER(PnO, Phame, Sex, Region, Tel),各属性分别表示参赛选手的编号、姓名、性别、地区和联系电话;

竞赛项目: CONTEST(CnO, Chame, Type, Date),各属性分别表示竞赛项目的编号、名称、类别和举办日期;

选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。

有关关系模式的说明如下:

(1)下划线标出的属性是表的主码。

(2)选手参赛表的属性Pno和Cno分别参照了选手表和竞赛项目表的主码。

(3)一个选手参加一项竞赛有一个名次和一个积分,名次有4个取值('一','二','三','无' )。另外,竞赛所在城市不能为空。

根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。

用户自定义完整性约束

【问题1】 (5分)

请将下面创建选手参赛表PC的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。

CREATE TABLE PC(
Pno CHAR(10) REFERENCES(a)(Pno),
Cno CHAR(3) REFERENCES(b)(Cno),
City CHAR(20)(c),
Rank CHAR(20)(d)
Point SMALLINT,
(e);

选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。

(a) PLAYER:Pno 参照选手表的主码 Pno。

(b) CONTEST:Cno 参照竞赛项目表的主码 Cno。

(c) NOT NULL:题目明确“竞赛所在城市不能为空”。

(d) CHECK(Rank IN ('一','二','三','无')):名次只有4个取值,用 CHECK 约束限制。

多个主键的实体完整性约束

主题题目要求定义实体完整性约束,在列声明中还没有定义主键

(e) PRIMARY KEY(Pno, Cno):由选手编号和竞赛项目编号联合作为主键。

【问题2】(6分)

查询所有未参加“Al”类别竞赛的选手,要求输出选手的编号(Pno),查询结果按照选手编号的升序排列。此功能由下面的SQL语句实现,请补全。

SELECT Pno FROM (f)
WHERE Pno (g) (
SELECT (h) FROM PC, Contest
WHERE (i)
(j) Type='Al' )
(k) Pon;

既然查询的结果是选手,输出的是选手编号,那么最外层select的就是选手表。填写PLAYER

k处,末尾要按照选手编号升序,必然是Order by

选手: PLAYER(PnO, Phame, Sex, Region, Tel)

竞赛项目: CONTEST(CnO, Chame, Type, Date),各属性分别表示竞赛项目的编号、名称、类别和举办日期;

选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。

内层联合了PC和CONTEST两表查询,where子句应当是等值条件

(h) PC.Pno:子查询返回参加Al类别竞赛的选手编号集合。

(i) PC.Cno = Contest.Cno:关联选手参赛表和竞赛项目表,确保比赛项目匹配。

(j) AND:连接条件,同时限定竞赛类别为'Al'。

(g)内层查询找出了参加AI类别竞赛的选手,外层筛选使用 NOT IN 进行排除

外键约束下的删除顺序

【问题3】(4分)

由于某种原因,编号为“E06”的竞赛项目在正式举办前被取消了。而此前系统中已经记录了一些选手的报名参赛情况,因此需要在系统中删除“E06”的竞赛项目记录,以及该竞赛的所有报名参赛纪录。根据问题1在选手参赛表PC上定义的参照完整性约束,此功能可以由下面的SQL语句实现,请补全。

(l) FROM (m) WHERE Cno= 'E06';

(n) FROM (o) WHERE Cno= 'E06';

竞赛项目: CONTEST(CnO, Chame, Type, Date),各属性分别表示竞赛项目的编号、名称、类别和举办日期;

选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。

(l) DELETE:删除操作的关键字。

(m) PC:先删除选手参赛表PC中相关报名记录,以解除外键约束。

(n) DELETE:删除操作的关键字。

(o) CONTEST:再删除竞赛项目表CONTEST中的项目记录。

PC表有外键参照CONTEST表,必须先删除子表(PC)中相关记录,才能成功删除父表(CONTEST)中的记录,否则会违反参照完整性约束。

5.

【说明】
某学生信息管理系统的部分数据库关系模式如下:
学生:Student ( stuno, stuname, stuage, stusex, schno),各属性分别表示学生的学号、姓名、年龄、性别,以及学生所属学院的编号;--- stuno 主键
学院:School ( schno, schname, schstunum ),各属性分别表示学院的编号、名称及学生人数;--- schno 主键
俱乐部:Club (clubno,clubname, clubyear, clubloc ),各属性分别表示俱乐部的编号、名称、成立年份和活动地点; --- clubno 主键
参加:JoinClub ( stuno, clubno. joinyear ),各属性分别表示学号、俱乐部编号,以及学生加入俱乐部 的年份。 --- stuno, clubno 主键
有关关系模式的说明如下:
(1) 学生的性别取值为‘F’和‘M’ (F表示女性,M表示男性)。
(2) 删除一个学院的记录时,通过外键约束级联删除该学院的所有学生记录。
(3) 学院表中的学生人数与学生表中的实际人数要完全保持一致。也就是说,当学生表中增减记录时,就要自动修改相应学院的人数。

根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。

级联删除CASCADE

【问题1】(4分)
请将下面创建学生表的SQL语句补充完整,要求定义实体完整性约束、参照完整性 约束,以及其他完整性约束。

CREATE TABLE Student (
stuno CHAR(11) ( a ),
stuname VARCHAR,
stuage SMALLINT,
stusex CHAR(1) ( b),
schno CHAR(3) ( c) ON DELETE ( d));

a) PRIMARY KEY:定义实体完整性,学号为主键。

(b) CHECK(stusex IN ('F','M')):用户定义完整性,限制性别只能取'F'或'M'。

(c) REFERENCES School(schno):参照完整性,学院编号外键参照学院表的主键。

(d) CASCADE:级联删除,当删除学院记录时,自动删除该学院所有学生。

视图

当视图的 SELECT 语句中,每一列都有一个明确的、无冲突的名字时,数据库可以自动推断列名,就可以不写括号。

当多表连接导致出现同名列,或者想重新给列命名时(相当于AS),就需要写括号

【问题2】(5分)
创建俱乐部人数视图,能统计每个俱乐部已加入学生的人数,属性有clubno> clubname 和clubstunum。对于暂时没有学生参加的俱乐部,其人数为0。此视图的创建语句如下, 请补全。

CREATE VIEW CS_NUMBER ( clubno, clubname, clubstunum ) AS
SELECT JoinClub.clubno, ( e ) , ( f  )
FROM JoinClub, Club
WHERE JoinClub.clubno = Club.clubno
( g ) BY JoinClub.clubno (h  )
SELECT clubno, clubname, 0 FROM Club
WHERE clubno NOT IN
(SELECT DISTINCT clubno FROM ( i));

参加:JoinClub ( stuno, clubno. joinyear ),各属性分别表示学号、俱乐部编号,以及学生加入俱乐部 的年份。

俱乐部:Club (clubno,clubname, clubyear, clubloc ),各属性分别表示俱乐部的编号、名称、成立年份和活动地点

(e) Club.clubname:输出俱乐部名称,因为clubno是主键,clubname函数依赖于它,可直接使用。注意其他列都附带表名的时候,也应该写club.,哪怕单独写clubname并不会报错

select一个有着group的count

(f) COUNT(*):题目要求统计每个俱乐部已加入学生的人数。算有多少行要联想到。

【实际执行的顺序是】
第1步:FROM + WHERE(做笛卡尔积,再过滤)
       ↓
第2步:GROUP BY(按 clubno 分组)
       ↓
第3步:SELECT(计算 COUNT(*),输出结果)

lubno	clubname	COUNT(*)
C01	篮球社	3(组C01有3行)
C02	足球社	2(组C02有2行)

这里的COUNT最后数的是每组的人数,然后其值作为表的一列。

一般不COUNT(列),因为可能漏掉空值行,而且性能较差!

......
WHERE JoinClub.clubno = Club.clubno
( g ) BY JoinClub.clubno (h  )
SELECT clubno, clubname, 0 FROM Club
WHERE clubno NOT IN
(SELECT DISTINCT clubno FROM ( i));

(g) GROUP:有按俱乐部编号分组统计。有聚合和非聚合函数就得group by

(h) UNION:将两部分结果合并:上半部分select是有学生的俱乐部统计人数,下半部分是无学生的俱乐部SELECT clubno, clubname, 0 FROM Club 给那些没有学生参加的俱乐部手动补上一个人数为 0 的记录。

注意:WHERE clubno NOT IN

(i) JoinClub:子查询找出已有学生参加的俱乐部编号,然后排除就得到了没学生的。

触发器

【问题3】(4分)
每当系统中新加或删除一个学生,就需要自动修改相应学院的人数,以便保持系统中学生人数的完整性与一致性。此功能由下面的触发器实现,请补全。

CREATE TRIGGER STU_NUM_TRG
AFTER INSERT OR DELETE ON ( j  )
REFERENCING new row AS nrow, old row AS orow FOR EACH(k  )
BEGIN
IF INSERTING THEN
UPDATE School ( l  )
END IF;
IF DELETING THEN
UPDATE School ( m);
END IF;
END;

(j) Student:触发器是针对学生表上的插入或删除操作触发的。

(k) ROW:因为需要引用每一行被插入或删除的数据(nrow 和 orow),所以必须是行级触发器。

REFERENCING new row AS nrow, old row AS orow FOR EACH ROW

REFERENCING 子句就是给 NEW 和 OLD 这两个系统默认的行引用,换成你自定义的别名 nrow 和 orow。

有些数据库之间使用NEW和OLD直接引用新、旧行,有些必须REFERENCING 子句显式地给新、旧行定义别名

(l) 插入学生时,将该学生所属学院的学生人数加 1,条件用新插入行的学院编号 nrow.schno

SET schstunum=schstunum+1 where School.schno= nrow.schno

WHERE schno = nrow.schno 的作用是把更新范围精确锁定到“该学生所属的那一个学院”,确保只改一条记录。不加 WHERE 会把所有学院的人数都改掉,造成数据混乱。

(m) 删除学生时,将该学生所属学院的学生人数减 1,条件用被删除行的学院编号 orow.schno

SET schstunum=schstunum-1 where School.schno=orow.schno
补充。这里是SET,不是为变量赋值,所以是普通等号,不是:=

【问题4】(2分)
查询年龄小于19岁的学生的学号、姓名及所属学院名,要求输出结果把同一个学院的学生排在一起。此功能由下面的SQL语句实现,请补全。

SELECT stuno, stuname, schname FROM Student, School WHERE Student.schno = School.schno
AND stuage <19 ( n ) BY ( o);

(n)order

(o)schname
学院:School ( schno, schname, schstunum ),各属性分别表示学院的编号、名称及学生人数;

6.

【说明】
某公司要对其投放的自动售货机建立商品管理系统,其数据库的部分关系模式如下:
售货机:VEM(VEMno,Location),各属性分别表示售货机编号、部署地点;
商品:GOODS(Gno,Brand,Price),各属性分别表示商品编号、品牌名和价格;
销售单:SALES(Sno,VEMno,Gno,SDate,STime),各属性分别表示销售号、售货机编号、商品编号、日期和时间;
缺货单:OOS(VEMno,Gno,SDate,STime),各属性分别表示售货机编号、商品编号、日期和时间。
相关关系模式的属性及说明如下:
(1)售货机摆放固定种类的商品,售货机内每种商品最多可以储存10件。管理员在每天结束的时候将售货机中所有售出商品补全。
(2)每售出一件商品,就自动向销售单中添加一条销售记录。如果一天内某个售货机上某种商品的销售记录达到10条,则表明该售货机上该商品已售完,需要通知系统立即补货,通过自动向缺货单中添加一条缺货记录来实现。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。

【问题 1】 (3 分)

请将下面创建销售单表的  SQL 语句补充完整,要求指定关系的主码和外码约束。

CREATE TABLE SALES(
       Sno CHAR(8)  (a)
       VEMno CHAR(5)   (b)
       Gno CHAR(8) (c) 
       SDate DATE,
       STime TIME);

销售单:SALES(Sno,VEMno,Gno,SDate,STime)

(a) PRIMARY KEY:定义实体完整性,销售号为主键。

(b) REFERENCES VEM(VEMno):定义外键约束,售货机编号参照售货机表的主键。

(c) REFERENCES GOODS(Gno):定义外键约束,商品编号参照商品表的主键。

分析Group by

【问题 2】 (4分)
创建销售记录详单视图 SALES_Detail ,要求按日期统计每个售货机上各种商品的销售数量,属性有 VEMno、Location 、Gno、Brand 、Price 、amount 和 SDate。为方便实现,首先建立一个视图 SALES_Total ,然后利用SALES_Total 完成视图 SALES_Detail 的定义。

CREATE VIEW SALES_Total(VEMno,Gno,SDate,amount) AS
     SELECT VENno ,Gno ,SDate ,count(*)
     FROM SALES
     GROUP BY  (d);
CREATE VIWE (e) AS
       SELECT  VEM.VEMno, Location, GOODS.Gno, Brand, Price, amount, SDate
       FROM VEM, GOODS, SALESTotal
             WHERE  (f)  AND  (g)

要求按日期统计每个售货机上各种商品的销售数量

售货机VEM(VEMno,Location),售货机编号、部署地点;

商品GOODS(Gno,Brand,Price),商品编号、品牌名和价格;

销售单SALES(Sno,VEMno,Gno,SDate,STime),销售号、售货机编号、商品编号、日期和时间;

第一个视图创建了总量amount供第二个视图使用、由于有group by,实际上count数的数量是分组后每组的数量并成为一列

(d) VEMno, Gno, SDate:按售货机、商品和日期分组,才能统计每天每台机器每种商品的销售数量。在出现了聚合列的情况下,剩下的非聚合列必须填到group by里面!

(e) SALES_Detail:创建第二个视图的名称。先创建了total视图,后面就是利用total创建detail视图

看到select from三个表,那么where子句肯定是三个表的两两等值连接

(f) VEM.VEMno = SALES_Total.VEMno:连接售货机表,获取地点信息。

(g) GOODS.Gno = SALES_Total.Gno:连接商品表,获取品牌和价格。


触发器

【问题 3】 (3分)
每售出一件商品,就自动向销售单中添加一条销售记录。如果一天内某个售货机上某种商品的销售记录达到 10 条,则自动向缺货单中添加一条缺货记录。需要用触发器来实现缺货单的自动维护。程序中的 GetTime()获取当前时间。

CREATE(h) OOS_TRG AFTER  (i)   ON SALES 
REFERENCING new row AS nrow 
FOR EACH  ROW
BEGIN
        INSERT INTO  OOS
             SELECT  SALES .VENno, (j) GetTime ()
             FROM SALES
             WHERE  SALES.VEMno = nrow.VEMno AND  SALES.Gno  = nrow.Gno AND SALES.SDate = nrow.SDate
            GROUP BY SALES.VEMno, SALES.Gno, SALES.SDate
                           HAVING count (*) > 0 AND mod(count (*),  10)=0;
END

(h) 填:TRIGGER

i:当销售单中插入新记录时,我们需要检查销量并可能向缺货单插入记录。因此触发事件是 INSERT

缺货单:OOS(VEMno,Gno,SDate,STime)

OOS为全码表,必须四个属性标识唯一的一行,INSERT语句必须插入所有列的值(一般考试都是插入全部列),因此:

(j)处应该为:SALES.Gno, SALES.Sdate

WHERE  SALES.VEMno = nrow.VEMno AND SALES.Gno  = nrow.Gno AND SALES.SDate = nrow.SDate

从 SALES 表中筛选与新插入行属于同一售货机、同一商品、同一天的销售记录。

HAVING count(*) > 0 AND mod(count(*), 10) = 0

该组内的销售记录数大于 0 且为 10 的整数倍时,触发插入操作。即每售出 10 件商品,自动生成一条缺货通知。mod就是是取模/求余数,计算被除数 ÷ 除数 的余数。

找最多用HAVING COUNT(*) >= ALL

【问题 4】 (3分)
查询当天销售最多的商品编号、品牌和数量。程序中的 GetDate()获取当天日期。

SELECT GOODS.Gno, Brand,   (k)
FROM GOODS,SALES
WHERE GOODS.Gno=SALES.GNO AND SDATE =GetDate()
GROUP BY (i)
HAVING(m) (SELECT count(*)
           FROM SALELS
           WHERE SDATE = GetDate()
           GROUP BY Gno);

(k) COUNT(*):统计当天每种商品的销售数量。

(l) GOODS.Gno, Brand:按商品编号和品牌分组,因为 SELECT 中出现了这两列非聚合函数,必须全部出现在 GROUP BY 中。

一条完整的 SQL 查询,执行顺序是这样的:

FROM:找到数据表,进行表连接(JOIN)。
WHERE:对原始数据进行行级过滤。
GROUP BY:将过滤后的数据按指定列进行分组。
HAVING:对分组后的数据进行组级过滤。
SELECT:从过滤后的小组里,抽取或计算要显示的列。
ORDER BY:对最终的输出结果进行排序。

(m) COUNT(*) >= ALL:

内层的SELECT count(*) FROM SALELS WHERE SDATE = GetDate() GROUP BY Gno之前已经接触过,select一个分组的count就是:数每组的个数,然后其值作为表的一列。也就是今天每个商品卖了几件。

where用来过滤行数据,having(条件表达式)过滤组数据,只保留 COUNT(*) >= ALL的组。

HAVING COUNT(*) >= ALL ( SELECT COUNT(*) ......

  • 内层的count是当天每种商品各卖了几个,是单纯的数字列,比如3、5、4......,然后ALL(子句)就是外层的count要比他们中任意一个都要大于或等于。

  • 外层的count就是某个商品编号和品牌构成的组,当天的销量。

【问题5】 (2分)
查询一件都没有售出的所有商品编号和品牌。

SELECT Gno ,Brand
FROM GOODS
WHERE GNO(N)
     SELECT DISTINCT GNO
     FROM(o);

(N) NOT IN:筛选未售出商品,即商品编号不在已售出商品列表中的商品。

(o) SALES:从销售单表中获取所有售出过的商品编号。

排除法where not in/not exist的区别

NOT IN 和 NOT EXISTS 无法在不改变语句结构的情况下直接等价替换。它们注定会导致子句的写法不同。外面有列是NOT IN,外面没有列是NOT EXIST

  • 子查询没有引用外层列 → 用 IN / NOT IN。

  • 要判断的列表里不可以有NULL

WHERE GNO (N) (SELECT DISTINCT GNO FROM (o))

这里子查询独立返回一列(商品编号列表),不与外层主查询的行进行关联。

  • 子查询引用了外层列(关联子查询) → 用 EXISTS / NOT EXISTS。

  • NOT EXISTS 是关联判断,子查询中只要关联条件不成立,EXISTS 就为 FALSE,不受 NULL 值干扰。

WHERE NOT EXISTS (
    SELECT 1 FROM SALES 
    WHERE SALES.Gno = GOODS.Gno
)

7.

【说明】
某单位公用车辆后勤服务部门数据库的部分关系模式如下:   
驾驶员:EMP(Eno,Ename, Age, Sex, telephone),各属性分别表示驾驶员工号、姓名、年龄、性别和电话号码;    
车辆:CAR(Cno,Brand,Capacity),各属性分别表示汽车车牌号、品牌名和排量;
调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),各属性分别表示调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。
奖金:BONUS(Eno,Year,Month,Amount),各属性分别表示驾驶员工号、年、月和当月的奖金数量。
有关车辆调度的相关说明如下:

公用车的行驶时间只能在工作时间内,因此规定调度表中每天安排发车的时间在上午07:00:00至下午18:00:00范围内。

【问题1】(4分)

请将下面创建调度关系的SQL语句的空缺部分补充完整,要求指定关系的主码、外码,以及调度表中每天安排发车的时间在上午07:00:00至下午18:00:00范围内的约束(由函数Time Get_time(DATETIME StartTime)返回出车的时间)。

CREATE TABLE SCHEDULE(
Sno CHAR(10),
Eno CHAR(10)       (a)      ,
Cno CHAR(8)        (b)      ,
StartTime DATETIME         (c)     ,
EndTime DATETIME,
PRIMARY KEY           (d)       );

调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。

  • (a) REFERENCES EMP(Eno):Eno 是外键,参照驾驶员表的主码。

  • (b) REFERENCES CAR(Cno):Cno 是外键,参照车辆表的主码。

  • (c) CHECK(Get_time(StartTime) BETWEEN '07:00:00' AND '18:00:00'):用户定义完整性约束,限制发车时间在上午7点到下午6点范围内。看到区间范围就

  • (d) Sno:调度号 Sno 为主键,唯一标识一次调度。

【问题2】(6分)
(1)创建所有'奥迪'品牌汽车的调度信息的视图AudiSCHEDULE,属性有Eno、Ename、Cno、Brand、StartTime和EndTime,请将下面SQL语句的空缺部分补充完整。

CREATE            (e)      
AS
SELECT  EMP,Eno,Ename, CAR,Cno,Brand, StartTime, EndTime
FROM EMP,CAR, SCHEDULE
WHERE            (f)        

驾驶员:EMP(Eno,Ename, Age, Sex, telephone),驾驶员工号、姓名、年龄、性别和电话号码;

车辆:CAR(Cno,Brand,Capacity),汽车车牌号、品牌名和排量;

调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。

(e) VIEW AudiSCHEDULE:创建视图的语法关键字,指定视图名称。

(f) EMP.Eno = SCHEDULE.Eno AND

CAR.Cno = SCHEDULE.Cno AND

CAR.Brand = '奥迪':三表连接条件,同时筛选出奥迪品牌车辆

这里要注意,除了两两连接之外,题目还要限定车辆品牌

触发器


(2)驾驶员的奖金在收车时间写入时,由出车时间段自动计算,并用触发器来实现奖金的自动维护,函数float Bonus_value(DATETIME StartTime, DATETIME EndTime)依据发车时间和收车时间来计算本次出车的奖金。系统在每月初自动增加一条该员工的当月奖金记录,初始金额为零。请将下面SQL语句的空缺部分补充完整。

CREATE     (g)     Bonus_TRG  AFTER       (h)        ON SCHEDULE
REFERENCING new row AS nrow
FOR EACH ROW
BEGIN
UPDATE BONUS
SET          (i)         
WHERE      (j)     AND   Year=Get_Year(nrow.StartTime)
AND Month= Get_Month(nrow.StartTime) ;
END

奖金:BONUS(Eno,Year,Month,Amount),驾驶员工号、年、月和当月的奖金数量。

(g) TRIGGER:创建触发器的关键字。

(h) UPDATE:触发器事件,在收车时间写入(即更新调度记录)时触发。

Bonus_value(DATETIME StartTime, DATETIME EndTime)依据发车时间和收车时间来计算本次出车的奖金。

触发器定义在 SCHEDULE 表上,奖金的计算根据发车时间和收车时间的NEW新插入行计算

(i) Amount = Amount + Bonus_value(nrow.StartTime, nrow.EndTime)累加本次出车的奖金,使用系统函数根据出车/收车时间计算。

(j) BONUS.Eno = nrow.Eno关联条件,定位到特定驾驶员当月的奖金记录。

选取最多用HAVING COUNT

【问题3】(5分)
请将下面SQL语句的空缺部分补充完整。
(1)查询调度次数最多的汽车车牌号及其品牌。

SELECT  CAR. Cno, Brand
FROM  CAR, SCHEDULE
WHERE  CAR.Cno =SCHEDULE.Cno
GROUP BY       (k)      
HAVING       (l)       (SELECT  COUNT(*)
FROM SCHEDULE
CROUP BY Cno);

(k) CAR.Cno, Brand:SELECT 中出现了 CAR.Cno 和 Brand,均为非聚合列,必须全部出现在 GROUP BY 中。

只要使用了 GROUP BY,SELECT 中出现的所有非聚合列必须全部出现在 GROUP BY 子句中

(l) COUNT(*)>= ALL:子查询返回每辆车的调度次数集合,COUNT(*) >= ALL 表示当前车的调度次数大于等于所有车的次数,即最大值。如果多辆车并列,会全部输出。找最多的题就联系到Group+having count组合

排除法用NOT IN

(2)查询所有在调度表中没有安排过“大金龙”品牌车辆的驾驶员工号和姓名。

SELECT Eno, Ename
FROM EMP
WHERE Eno          (m)     (
SELECT Eno
FROM         (n)    
WHERE        (o)       
AND  brand=‘大金龙');

驾驶员:EMP(Eno,Ename, Age, Sex, telephone),驾驶员工号、姓名、年龄、性别和电话号码;

车辆:CAR(Cno,Brand,Capacity),汽车车牌号、品牌名和排量;

调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。

(m) NOT IN:筛选“不在”已安排大金龙车辆的驾驶员集合中。

这里where后面跟着一个列,肯定不是WHERE NOT EXIST

(n) SCHEDULE, CAR:子查询需要连接调度表和车辆表才能获取品牌信息。

(o) SCHEDULE.Cno = CAR.Cno:两表连接条件,确保车辆匹配。

8.

【说明】
某大型集团公司的数据库的部分关系模式如下:
员工表:EMP( Eno,Ename,Age,Sex,Title),各属性分别表示员工工号、姓名、年龄、性别和职称级别,其中性别取值为“男”“女”;
公司表:COMPANY( Cno,Cname,City),各属性分别表示公司编号、名称和所在城市;
工作表:WORKS( Eno,Cno,Salary),各属性分别表示职工工号、工作的公司编号和工资。
有关关系模式的属性及相关说明如下:
(1)允许一个员工在多家公司工作,使用身份证号作为工号值。
(2)工资不能低于1500元。
根据以上描述,回答下列问题:

【问题1】(4分)

请将下面创建工作关系的SQL语句的空缺部分补充完整,要求指定关系的主码、外码,以及工资不能低于1500元的约束。

CREATE TABLE WORKS(
Eno CHAR(10) (a) ,
Cno CHAR(4) (b) ,
Salary int (c) ,
PRIMARY KEY (d) ,
);

工作表:WORKS( Eno,Cno,Salary),职工工号、工作的公司编号和工资

(a) REFERENCES EMP(Eno):定义外键约束,参照员工表的主键。因为题目已经说明此列是主键之一,所有不可能是UNIQUE

(b) REFERENCES COMPANY(Cno):定义外键约束,参照公司表的主键。

(c) CHECK(Salary >= 1500):用户定义完整性约束,保证工资不低于1500元。

(d) Eno, Cno主键的题目一定要小心主键属性是不是只有一个

多表连接+限定条件

【问题2】(6分)
(1)创建女员工信息的视图FemaleEMP,属性有Eno、Ename、Cno、Cname和Salary,请将下面SQL语句的空缺部分补充完整。

CREATE (e)
AS
SELECT EMP.Eno,Ename,COMPANY.Cno,Cname,Salary
FROM EMP, COMPANY, WORKS
WHERE (f) ;

员工表:EMP( Eno,Ename,Age,Sex,Title),员工工号、姓名、年龄、性别和职称级别,其中性别取值为“男”“女”;

公司表:COMPANY( Cno,Cname,City),公司编号、名称和所在城市;

工作表:WORKS( Eno,Cno,Salary),职工工号、工作的公司编号和工资。

(e) VIEW FemaleEMP:创建视图的语法关键字及视图名称。

(f) EMP.Eno = WORKS.Eno AND

COMPANY.Cno = WORKS.Cno AND

EMP.Sex = '女':三表连接条件,之后不要忘记加上题目的条件!!!并筛选出女员工。

(2)员工的工资由职称级别的修改自动调整,需要用触发器来实现员工工资的自动维护,函数float Salary_value(char(10) Eno)依据员工号计算员工新的工资。请将下面SQL语句的空缺部分补充完整。

CREATE (g) Salary_TRG AFTER (h) ON EMP
REFERENCING new row AS nrow
FOR EACH ROW
BEGIN
UPDATE WORKS
SET (i)
WHERE (j) ;
END

(g) TRIGGER:创建触发器的关键字。

(h) UPDATE:触发事件为更新员工表(职称级别修改即 UPDATE 操作)。

(i) Salary = Salary_value(nrow.Eno):使用函数根据新员工号计算并设置新工资。

(j) WORKS.Eno = nrow.Eno关联条件,UPDATE的是哪行?是和新插入的那行一样的行
【问题3】(5分)
请将下面SQL语句的空缺部分补充完整。
(1)查询员工最多的公司编号和公司名称。

SELECT COMPANY.Cno,Cname
FROM COMPANY,WORKS
WHERE COMPANY.Cno= WORKS.Cno
GROUP BY (k)
HAVING (l) ( SELECT COUNT(*)
FROM WORKS
GROUP BY Cno
);

(k) COMPANY.Cno, Cname:SELECT 中的两个非聚合列都必须出现在 GROUP BY 中。

(l) COUNT(*) >= ALL:子查询返回每个公司的员工数集合,当前组的员工数大于等于所有值即为最大值。

(2)查询所有不在“中国银行北京分行”工作的员工工号和姓名。

SELECT Eno,Ename
FROM EMP
WHERE Eno (m) (
SELECT Eno
FROM (n)
WHERE (o)
AND Cname=‘中国银行北京分行’
);

FROM是Eno在的表,要连接的是Cname在的表

(m) NOT IN:外层列 Eno 紧接子查询,用 NOT IN 排除在目标公司工作的员工。

(n) WORKS, COMPANY:Eno在Work里,Cname在COMPANY里

(o) WORKS.Cno = COMPANY.Cno:两表连接条件。


评论