数据库作战记录1

【3.4】

【a题】☆☆☆☆☆

涉及表格:

人员------participated.driver_id

交通事故------accident

要统计driver_id,要用count(*)。约束是2017年,约束的字段是accident表的year字段,因此思路是先交两个表格,那么必须以外域键为约束,然后再用2017为约束限制。

select count(*)

from accident, participated

where accident.report_number=participated.report_number and year = 2017

写错了:

因为这会筛选出来所有在2017年发生车祸的所有记录,而不是人数,可能有菜逼司机撞了六七次。因此count对象要distinct,而且筛选字段是driver_id

【正解】

select count(distinct driver_id)

from accident, participated

where accident.report_number=participated.report_number and accident.year = 2017

【b题】☆☆☆☆☆

涉及表格:

汽车------car

ID为X的人------owns

思路:找到这个人拥有的所有汽车,再约束年份为2010,涉及两个表格,因此要用license_plate外域键做约束,再用car.year=2010再次约束

delete from car, owns**[启发1]**

where car.license_plate = owns.license_plate and owns.driver_id = '12345' and car.year=2010

写错了:

严重语法错误:不能同时删两个表

标准 SQL 的 DELETE 语句一次只能删除一个表的数据 。你不能写 DELETE FROM table1, table2。题目要求是"删除汽车",所以只能 DELETE FROM car

正确思路与写法:

我们要从 car 表中删除数据,条件是:这辆车的车牌号必须出现在 owns 表中(且属于司机 '12345'),并且年份是 2010。

启发1:删除只能删一个表,因此但凡涉及其他表都有用子查询或ETAwith语句。

启发2:用in在子查询中,必须前后一致

【正解】

delete from car

where year = 2010 and license_plate in (

select license_plate[启发2]

from owns

where driver_id='12345'

)

【3.8】

【a题】★☆☆☆☆

考点:Except使用

涉及表格:

客户的ID------用borrower不要用depositor

有账户------depositor

思路:有账号的人是customer,借了钱的是borrower,ID可以差集出来,差集except要求列的数量一致

【正解】

select ID

from depositor

except

select ID

from borrower

【b题】★☆☆☆☆

考点:in的使用,in代表有一个匹配即可,全匹配要用双否

涉及表格:客户------customer

【正解】

select ID

from customer

where (customer_street, customer_city) in (

select customer_street, customer_city

from customer

where ID='12345'

)

【c题】★☆☆☆☆

考点:至少一位的表达

涉及表格:支行------branch

客户------customer

思路:至少一位 some/Any(表格),先子查询出该分行中开设了账户的客户

select branch_name

from branch

where branch_city = Any(

select customer_city

from customer, depositor

where customer.ID=depositor.ID and customer.customer_street="Harrison"

)

不对

涉及的表格是branch account customer depositor

因此要把所有内容笛卡尔积出来,筛选

【正解】

select b.branch_name

from account as a, branch as b, customer as c, depositor as d

where a.branch_name=b.branch_name and c.ID=d.ID and a.account_number = d.account_number and c.customer_city="Harrison";

【3.9】

【a题】☆☆☆☆☆

设计表格:雇员------employee

工作------works

但是二者之间没有之间关系。必须引入work表

select e.ID e.person_name e.city

from employee as e, work as w, company as c

where e.ID=w.ID and w.company_name= c.company_name and c.company_name='First Bank Corporation'

冗余了,不需要company表,company_name包含在works中了

【正解】

select e.ID e.person_name e.city

from employee as e, work as w

where e.ID=w.ID and w.company_name='First Bank Corporation';

【b题】☆☆☆☆☆

select e.ID e.person_name e.city

from employee as e, work as w, company as c

where e.ID=w.ID and w.company_name= c.company_name and c.company_name='First Bank Corporation' and w.salary>10000;

同上,冗余了,不需要company表

【正解】

select e.ID e.person_name e.city

from employee as e, work as w

where e.ID=w.ID and w.company_name='First Bank Corporation' and w.salary>10000;

【c题】☆☆☆☆☆

考点:Except的使用

使用except

select e.ID

from employee as e, company as c

where except (

select e.ID

from e,c

where c.company_name='First Bank Corporation'

)

思路是对的,但是except使用错误

except是要用在两个表中,但是不是嵌套查询而是平级查询

因此:

【正解】

select ID

from employee

except

select ID

from works

where works.company_name='First Bank Corporation'

【d题】 ★☆☆☆☆

考点:全称量词ALL的使用

思路:先聚集函数得到公司最高值,或者ALL一次,

select e.ID

from employee as e, works as w

where e.ID=w.ID and w.salary> ALL(

select salary

from e,w,company as c

where c.company_name='First Bank Corporation' and e.ID=w.ID

)

子查询别名错误 :子查询的 FROM 子句中不能直接写 from e, w,必须写完整的表名 from employee e, works w

【正解】

select e.ID

from employee as e, works as w

where e.ID=w.ID and w.salary> ALL(

select w2.salary

from works as w2

where w2.company_name='First Bank Corporation' and e.ID=w.ID

)

【e题】★★☆☆☆

考点:自交使用

先找到SBC的所有所在城市,然后找这些城市有哪些公司,典型的自交问题【单表排查类型】

子查询是select city,

select c.company_name

from company as c

where c.city in (

select c.city

from c

where c.company_name="Small Bank Corporation"

)

修正后:

【正解】

select c1.company_name

from company as c1, company as c2

where c2.company_name = c1.company_name and c1.company_name != 'Small Bank Corporation' and c2.company_name = 'Small Bank Corporation'

【f题】★☆☆☆☆

考点:全称量词ALL的使用

思路:统计问题用count

select c.company_name

from company as c, works as w

where c.company_name = w.company_name and count(distinct ID) >= (

select count(distinct ID)

from c,w

where c.company_name = w.company_name

)

依然是老问题,companyname已经在works中了,直接用works即可

比较逻辑错误 :你不能拿一个具体的 count 去和一个子查询的 count 直接在 WHERE 里比(除非用 HAVING

🎯 考察点: GROUP BY 分组统计、HAVING 子句过滤分组结果、ALL 与聚合函数的结合。

【正解】

select c.company_name

from works as w

group by w.company_name
having count(w.ID) > ALL(
select count(w2.ID)

from works as w2

group by w2.company_name

)

如果取一个的话,也可以用order解决

select company_name

from works

group by company_name

order by count(works) ASC

【g题】★☆☆☆☆

思路:明显的分桶问题 groupby 聚类,

select

from company as c. works as w

where c.ID=w.ID

group by c.company_name

having avg(salary)>

【正解】

select w.company_name

from works as w

group by w.company_name
having avg(w.salary)>(
select avg(w2.salary)

from works w2

where w2.company_name="First Bank Corporation"

)

【问题】

这套题影响最大的是:要找对表格,不要引入冗余表

except的使用是平级表

子查询的from必须写完整表名,不可以用父查询的简写,且要别名

单表内部关系排查使用自交思路(比较同一个表中属性的关系

不能拿一个具体的 count 去和一个子查询的 count 直接在 WHERE 里比(除非用 HAVING

where c.company_name = w.company_name and count(distinct ID) >= (
select count(distinct ID)

having avg(w.salary)>(
select avg(w2.salary)

什么时候写 SELECT X,什么时候写 SELECT table.X

核心原则:当列名在查询涉及的表中不唯一时,必须加表名(或别名)前缀;否则可以省略。

【3.15】

【a题】★★★★★

考点:双重否定

涉及表格:

账户------account

客户------customer depositor,二者有通外域键

支行------branch

思路:关键在于如何表达"在所有支行都有",这明显是双重否定

select *

from branch as b

where b.branch_city='Brooklyn' and

但是我不会

唯一一种办法是假设用户不会重复在一家支行开户,这样可以用在BK银行开户数量=支行数量来解。

【正解】

【计数法求解】

思路:客户在 Brooklyn 支行开的账户数 == Brooklyn 支行总数

核心属性就是account_number,先where过滤出在BK银行有账号的用户,然后按id将用户groupby,然后查每个桶的用户的branch_name数量和BK银行分行数量是否一致

select *

from branch as b, depositor as d, account as a

where b.branch_name="BK" and b.branch_name=a.branch_name and a.account_number = d.account_number

group by d.ID
having count(distinct b.branch_name) =(
select count *

from branch

where branch_name="BK"

)

【双重否定做法】

不存在这样的支行(在BKN的支行)

该用户没有在这里有账户

select c.customer_name

from deposit as d, customer as c

where c.ID=d.ID and not exist(

select *

from branch

where branch_city="BKN" and not exists (

select *

from account

where account.branch_name=branch.branch_name

)

)

不对,

select customer_name

from customer as c

where not EXISTS(

select *

from branch

where branch_city="BKN" and not EXISTS(

select *

from account,deposit

where account.branch_name = branch.branch_name and deposit.ID=c.ID --该用户没有在这里有账户

)

)

【b题】☆☆☆☆☆

【正解】

select sum(amount)

from loan

【c题】★☆☆☆☆

考点:where中不能用聚集函数

select b1.branch_name

from branch as b1, branch as b2

where b1.assets > min(b2.assets)

错误,不能在where中用聚集函数

【正解】

select branch_name

from branch

where assets>(

select min(asset)

from branch

where branch_name="BKN"

)

【3.16】

【a题】☆☆☆☆☆

【正解】

select e.ID, person_name

from employee as e, works as w, company as c

where e.ID=w.ID and w.company_name=c.company_name and e.city=company.city

【b题】★★★☆☆

考点:高级自交使用

涉及表:

manages

employee

【正解】

select e.ID, person_name

from employee as e,employee as m, maneges

where e.ID = manages.ID and m.ID=manages.manager_id and e.street=m.street and e.city=m.city

【c题】★☆☆☆☆

【正解】

select e.ID, e.person_name

from employee as e, works as w1

where e.ID=w1.ID and w.salary > (

select avg(salary)

from works as w, company as c

where w.company_name=c.company_name

)

【d题】★★★★★

考点:多重映射

按公司的名字gb员工的工资,得到sum,然后父查询select min,得到的是最小的sum,但要映射到公司名字上,因此要再套一层having sum(salary)=这个最小值

【正解】

select company_name

from works

group by company_name

having sum(salary) =

(

select min(total)

from (

select sum(w.salary) as total

from works as w, company as c

where w.company_name = c.company_name

group by c.company_name

) as sum_salary

)

还有一个解法,就是排序取最小,但只能取出最小的一个

select company_name

from works

group by company_name

order by sum(salary) ASC

LIMIT 1;

【3.17】

【a题】☆☆☆☆☆

【正解】

update works

set salary = salary*1.1

where company_name="First Bank Corpoeration"

【b题】★★☆☆☆

考点:约束条件无法通过要修改的表约束,必须要用子查询

update works

set salary = salary*1.1

where company_name="First Bank Corpoeration" and ID in (

select ID

from employee,manages

where employee.ID=manages.manager_id

)

不对,不需要连接 employee 表,因为 managesworks 都通过 ID 关联即可

【正解】

update works

set salary = salary*1.1

where company_name="First Bank Corpoeration" and ID in (

select distinct manager_id

from manages

)

【c题】☆☆☆☆☆

【正解】

delete from works

where company_name="First Bank Corpoeration"

【3.21】

【a题】☆☆☆☆☆

至少一本-》in秒了

【正解】

select memb_no,name

from member

where member_no in (

select member_no

from member as m, book, borrowed as b

where book.publisher="MH" and b.isbn=book.isbn and b.memb_no = m.menb_no

)

【b题】★★★★★

考点:双重否定

类似3.15 a题,双否我肯定是写不出来的->不存在一本没借,因此还是用计数法

【正解】

【计数法】

select memb_no,name

from member,book,borrowed

where member.memb_no=borrowed.memb_no and borrowed.isbn=book.isbn

group by memb_no,name

having count(distinct isbn)(--拥有和这个出版社isbn一样多的isbn,就是找一个能唯一标识全部的属性

select distinct isbn

from book

where publiser="GH"

)

【双重否定法】

双重否定解释:

  • 外层 NOT EXISTS:确保"不存在这样的书"
  • 内层 NOT EXISTS:这本书是该会员没借过的
  • 合起来:"不存在一本 McGraw-Hill 的书是该会员没借过的" → 即他借了所有 McGraw-Hill 的书。

select memb_no,name

from member as m

where not exists(

select *

from book

where publisher ="GH" and not exists(--不存在这样的书

select *

from borrowed as br

where m.memb_no=br.memb_no and book.isbn=br.isbn

)

)

【c题】★★★★☆

**考点:**select的内容必须出现在groupby中!

显然的分组统计问题,groupby出版社,然后统计每个成员借的书,大于5输出

select m.memb_no,m.name

from member as m, book,borrowed as br

where m.memb_no=br.memb_no and br.isbn=book.isbn

group by book.publisher

having count(*)>5;

错误!select的内容必须出现在groupby中!!!

【正解】

select m.memb_no,m.name

from member as m, book, borrowed as br

where m.memb_no=br.memb_no and br.isbn=book.isbn

group by book.pulisher, m.memb_no, m.name

having count(*)>5;

【d题】★★★★☆

考点:with ATE的使用 小数除法的用法

总借出:

with

(select count(*)

from borrowed)

as total_bk

with

(select count(*)

from member)

as total_mem

select total_bk/total_mem as avg_bk

整数除法输出仍然是整数!!!必须CAST AS FLOAT 才行!!!

CTE错误!

【正解】

with total_bk AS(

select count(*) AS cnt from borrowed

),

total_mem AS(

select count(*) AS cnt from book

)

select CAST(b.cnt AS FLOAT)/(m.cnt) AS avg_bk

from total_bk as b, total_mem as m;

更简洁的:

select

CAST(count(br.isbn)AS FLOAT)/(select * from member) AS avg_bk

from borrowed br;

相关推荐
哆啦A梦158818 小时前
Springboot整合MyBatis实现数据库操作
数据库·spring boot·mybatis
Zzzzmo_18 小时前
【MySQL】JDBC(含settings.xml文件配置/配置国内镜像以及pom.xml文件修改)
数据库·mysql
FirstFrost --sy19 小时前
MySQL内置函数
数据库·mysql
2401_8796938719 小时前
将Python Web应用部署到服务器(Docker + Nginx)
jvm·数据库·python
reembarkation19 小时前
光标在a-select,鼠标已经移出,下拉框跟随页面滚动
java·数据库·sql
eggwyw19 小时前
MySQL-练习-数据汇总-CASE WHEN
数据库·mysql
星轨zb20 小时前
通过实际demo掌握SpringSecurity+MP中的基本框架搭建
数据库·spring boot·spring security·mp
treacle田20 小时前
达梦数据库-配置本地守护进程dmwatcher服务-记录总结
数据库·达梦数据库·达梦数据库local数据守护
wyt53142920 小时前
Redis的安装教程(Windows+Linux)【超详细】
linux·数据库·redis
CeshirenTester20 小时前
从数据库到结构化用例:一套可落地的测试智能体架构
数据库·架构