数据库第一次小测复习
本文最后更新于 2026年4月5日 下午
给出这样的一个模式:
employee(person_name, street, city)
works(person_name, company_name, salary)
company(company_name, city)找到薪水 $\ge$ 数据库中所有人的薪水的员工姓名
解:关系代数中没有MAX()函数,使用差集来解决:
- 找出所有“不是最高薪水”的人。
- 用“所有人”减去这些“不是最高薪水”的人。
$$\text{LowerPay} = \Pi_{works.person_name}(works \bowtie_{works.salary < d.salary} \rho_d(works))$$
$$\text{Result} = \Pi_{person_name}(works) - \text{LowerPay}$$
如何使用基本运算符描述$\div$运算:
基本思路:列出全集,用全集做差找出缺失的组合,再剔除缺失的这些
假设 $R$ 的属性是 $(A, B)$,$S$ 的属性是 $(B)$,我们要算 $R \div S$:
$T_1 = \Pi_A(R)$ 找到所有可能符合条件的
$T_2 = T_1 \times S$ 找到全集,产生所有可能的$(A,B)$组合
$T_3=T_2-R$ 得到缺失的部分
$T_4 = \Pi_A(T3)$ 只需要$A$
$Result = T_1 - T_4 = \Pi_A(R) - \Pi_A((\Pi_A(R) \times S) - R)$
标量子查询的练习:
In University Schema, find the sections that had the maximum enrollment in Fall 2017
使用with子查询,首先计算一遍每个sec的选课人数;然后再使用标量子查询:
with cte as (
select course_id, sec_id, count(*) as enrollment
from takes
where takes.year = 2017 and takes.semester = 'Fall'
group by course_id, sec_id, year, semester
-- 这里带不带year semester无所谓,where已经筛过了
)
select course_id, sec_id
from cte
where enrollment = (select max(enrollment) from cte)凡是出现在 SELECT 后面、但没有被聚合函数(如 COUNT, SUM)包裹的列,必须全部写在 GROUP BY 后面。
所谓标量子查询,就是这一句:where enrollment = (select max(enrollment) from cte)。
当然,也可以用窗口函数解决此题目:
with cte as (
select course_id, sec_id, count(*) as cnt
rank() over (
partition by year, semester
order by count(*) desc
) as rk
from takes
where semester = 'Fall' and year = 2017
group by course_id, sec_id, year, semester
)
select course_id, sec_id
from cte
where rk = 1-- Find each customer who has an account at *every* branch located in 'Brooklyn'
select customer.ID, customer.customer_name
from customer
natural join depositor
join account on account.account_number = depositor.account_number
join branch on branch.branch_name = account.branch_name
where branch.branch_city = 'Brooklyn'
group by customer.ID, customer.customer_name, account.branch_city
having count(distinct branch.branch_name) = (select count(*) from branch where branch_city = 'Brooklyn')这题易错点在于最后一个地方需要是distinct branch.branch_name,因为比如一个支行开很多户,不符合题意。