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用来将匹配阶段产生的数据中检索过滤。

什么是子查询?

https://zhidao.baidu.com/question/270020565.html

查询系列

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');

排序系列

posted @ 2020-09-27 22:51  童年の波鞋  阅读(27)  评论(0编辑  收藏  举报