sql 题目汇总
前置知识
笛卡尔集
SELECT A.*, B.*
FROM A, B
-- 不加WHERE条件,就是笛卡尔积
inner join
等值连接:在表中存在至少一个匹配时才返回行数据,即只返回两个表中联结字段相等的行
https://www.runoob.com/sql/sql-join-inner.html
https://www.cnblogs.com/assasion/p/7768931.html
where和 join on 哪个效率高?
看情况吧,二者的使用前提不一样
where:匹配阶段不会被使用,在匹配阶段完成,WHERE用来将匹配阶段产生的数据中检索过滤。
什么是子查询?
查询系列
c. 组合两个表
表1: Person
+-------------+---------+
| 列名 | 类型 |
+-------------+---------+
| PersonId | int |
| FirstName | varchar |
| LastName | varchar |
+-------------+---------+
PersonId 是上表主键
表2: Address
+-------------+---------+
| 列名 | 类型 |
+-------------+---------+
| AddressId | int |
| PersonId | int |
| City | varchar |
| State | varchar |
+-------------+---------+
AddressId 是上表主键
编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,都需要基于上述两表提供 person 的以下信息:
FirstName, LastName, City, State
思路
这里考察的是使用 left join 时,on 和 where 的合理选择:
- on:生成临时表 A 时,无论 on 后的条件是否成立,都会返回左表 P 一个值(不存在返回 NULL)
- where:生成临时表 A 后,对临时表的数据进行过滤
select P.FirstName, P.LastName, A.City, A.State
from Person as P left join Address as A
on (P.PersonId = A.PersonId);
c. 查找重复的电子邮箱
编写一个 SQL,查找 Person 表中所有重复的电子邮箱。
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
思路
看到找重复,就要想到 group by
函数,最朴素的想法
select Email from (
select Email, count(Email) as cnt
from Person
group by Email
) as ans_t where ans_t.cnt>1;
聚集函数要对全列数据进行计算,数据必须结果集事先确定,而where还在确定结果的过程中,所以while不能和count这些聚合函数一起使用,所以要在count位置之前写聚合函数只能使用having
select Email
from Person
group by Email
having count(Email)>1;
sql 语句执行顺序:https://www.cnblogs.com/wdt1/articles/13742234.html
c. 超过经理收入的员工
-- 笛卡尔积+过滤
select a.Name as 'Employee'
from Employee a, Employee b
where a.ManagerId is not null and a.Salary>b.Salary And a.ManagerId=b.id;
-- 内连接(自动去除null数据)
select a.Name as Employee
from employee a
inner join employee b
on a.ManagerId=b.id and a.salary>b.salary;
-- 左连接
Select a.Name as 'Employee'
From Employee a join Employee b
on a.Salary>b.Salary and a.ManagerId=b.id;
-- 子查询
select a.Name as 'Employee'
from Employee a
where a.salary >
(select b.salary from Employee b where a.ManagerId=b.id);
c. 大的国家
查询面积超过 300 万平方公里,或者人口超过 2500 万的国家
-- 粗暴做法
select name, population, area
from World
where area>3000000 or population>25000000;
--
修改系列
c. 交换工资
给定一个 salary 表,如下所示,有 m = 男性 和 f = 女性 的值(不能有临时表和select语句)
-- 写法一
update salary
set sex = (
case sex
when 'm' then 'f'
else 'm'
end
);
-- 写法二:if (条件,返回值1,返回值2),当条件成立,返回返回值1;否则返回返回值2
update salary set sex = if (sex='f','m','f');