🦌的刷题手札
长期没接触SQL,忘记的一干二净,本篇仅作为「个人刷题笔记」,记录一些简单的SQL学习过程。欢迎指正批评。
SQL
Leetcode-584. 寻找用户推荐人 SQL 简单(Simplist)
Question
Answer:
select name
from customer
where referee_id is NULL OR referee_id <> 2;
Note:
- is NULL VS = NULL :
在SQL中,NULL是一种特有的数据类型,其等价于没知有任何值、是未知数。NULL与0、空道字符串、空格都不同,只有非ANSI SQL标准中data=NULL等同于data IS NULL。
答案链接 - 不等于可以使用 <>
Leetcode 586. 订单最多的客户 SQL 简单
Question:
Answer:
select customer_number
from Orders
Group by customer_number
having count(order_number) = (
select max(sum1)
from (
select customer_number, count(order_number) as sum1
from Orders
group by customer_number
)tmp
);
【Note】group by的相关知识点:
group by:分组查询,一般和聚合函数配合使用。
【使用原则】select 后面的列中,没有使用聚合函数的列,必须出现在 group by 后面!!
【注意事项】
- group by 必须在where之后,having之前。
- where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。(过滤行)
- having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。(过滤分组)
- 多个NULL将被分在一组。
- 使用WITH ROLLUP可得到每个分组以及其汇总级别的值。
- ORDER BY放在HAVING后面。
- SELECT-FROM-WHERE-GROUP BY-HAVING-ORDER BY-LIMIT
Leetcode-181. 超过经理收入的员工 SQL 简单(Simplist)
Question
Ans
方法1:自链接
select a.name as Employee
from Employee as a, Employee as b
where a.Salary > b.Salary and a.managerId=b.id;
方法2:子链接
select e.name as Employee
from Employee as e
where Salary>(select Salary from Employee where id=e.managerId);
Leetcode-180. 连续出现的数字(中等)
Question
我的想法是建立一个自连接的表,配合子查询进行操作
select c.Num as ConsecutiveNums
from (
select l.Num, count(l.Num) as couNum
from Logs l, Logs l1
where (l.id = l1.id-1 OR l.id = l1.id-2) AND (l.num = l1.num)
) c
where c.couNum >= 3;
但问题就出现在,当出现两个连续数字的时候,会满足where的条件然后返回。
于是看了官方的解答,明白了可以使用三个表的自连接,配合distinct使用
select distinct l.Num as ConsecutiveNums
from Logs l, Logs l1, Logs l2
where
l.id = l1.id-1
and l1.id = l2.id-1
and l.num = l1.num
and l1.num = l2.num
目前对运行速度还没有改进要求,之后再来填坑。
Leetcode-182. 查找重复的电子邮箱 (简单)
最基础的题目,几乎是我在学习SQL之后第一道写的题目。但是发现自己好像每次都用自连接来解决问题,导致真的会很慢:
SELECT distinct p1.Email as Email
FROM Person p1, Person p2
WHERE p1.Id<p2.Id
AND p1.Email=p2.Email
查看评论区后整理:
方法1:自连接
方法2:having+count聚合
select Email from Person group by Email having count(Email) > 1;
方法3:子查询
select Email from (select count(1) as t, Email from Person group by Email) r where r.t > 1;
具体哪个快呢?
1略快于2,快于3
Leetcode-1084. 销售分析III(简单)
编写一个SQL查询,报告2019年春季才售出的产品。即仅在2019-01-01至2019-03-31(含)之间出售的商品。
# My code
select z.product_id, z.product_name
from (
select p.product_id, p.product_name, max(s.sale_date) max_d, min(s.sale_date) min_d
from Product p , Sales s
where p.product_id = s.product_id
group by p.product_id) z
where DATE(z.max_d) <= '2019-03-31' AND DATE(z.min_d)>='2019-01-01';
# from comment
select p.product_id,p.product_name
from product p right join sales s
on p.product_id=s.product_id
group by p.product_id
having min(sale_date)>='2019-01-01' and max(sale_date)<='2019-03-31';