sql练习题单-知识点总结 - 教程

一、题单

力扣

题目分类经典题目核心考点难度
基础查询与过滤1757. 可回收且低脂的产品 
595. 大的国家 
1148. 文章浏览 I 
WHERE条件过滤、OR逻辑运算符简单
表连接(JOIN)1378. 使用唯一标识码替换员工ID 
1068. 产品销售分析 I 
577. 员工奖金 
1581. 进店却未进行过交易的顾客 
1251. 平均售价 
LEFT JOININNER JOIN、多表连接、连接条件与过滤简单-中等
排序、分组与聚合182. 查找重复的电子邮箱 
1484. 按日期分组销售产品 
619. 只出现一次的最大数字 
1174. 即时食物配送 II 
GROUP BYHAVINGCOUNT(DISTINCT)GROUP_CONCAT简单-中等
子查询与高级功能176. 第二高的薪水 
570. 至少有5名直接下属的经理 
185. 部门工资前三高的所有员工 
610. 判断三角形 
子查询、CASE WHENIFNULL/COALESCE、逻辑判断中等
窗口函数178. 分数排名 RANK()DENSE_RANK()ROW_NUMBER()

题目详解:

14841484. 按日期分组销售产品 - 力扣(LeetCode)

SELECT
    sell_date,
    COUNT(DISTINCT product) AS num_sold,
    GROUP_CONCAT(DISTINCT product ORDER BY product SEPARATOR ',') AS products
FROM
    Activities
GROUP BY
    sell_date
ORDER BY
    sell_date ASC;
部分说明
GROUP_CONCAT(...)MySQL 特有函数,把一组中的多个值拼接成一个字符串
DISTINCT product只取不同的产品名(去重)
ORDER BY product拼接时按产品名的字母顺序排列
SEPARATOR ','用逗号 , 作为分隔符(默认就是逗号,可省略)
AS products给拼接结果起别名
函数/语法用途注意
GROUP BY按某字段分组是聚合操作的基础
COUNT(DISTINCT col)统计去重后的数量非常常用
GROUP_CONCAT()将多行值拼成字符串MySQL 特有
ORDER BY in GROUP_CONCAT控制拼接顺序否则顺序不确定
SEPARATOR ','自定义分隔符可改为 ; 或 `

这种写法常用于:

  • 日报:每天卖了哪些商品?
  • 用户行为分析:每个用户购买了哪些类目?
  • 标签系统:每个人有哪些标签?

总结一句话:

这段 SQL 的核心思想是:

“按日期分组 → 去重统计 → 拼接字符串”

178

SELECT
  S.score,
  DENSE_RANK() OVER (
    ORDER BY
      S.score DESC
  ) AS 'rank'
FROM
  Scores S;

这是最核心的部分,我们拆开讲:

部分说明
DENSE_RANK()一个窗口函数(Window Function),用于生成密集排名
OVER (...)定义窗口函数的作用范围和排序规则
ORDER BY S.score DESC按分数 从高到低 排序(DESC = 降序)
AS 'rank'将排名结果命名为 'rank'(注意:rank 是保留字,所以用引号)

176

# Write your MySQL query statement below
SELECT
    IFNULL(
      (SELECT DISTINCT Salary
       FROM Employee
       ORDER BY Salary DESC
        LIMIT 1 OFFSET 1),
    NULL) AS SecondHighestSalary
1. 内层子查询:找出第二高的薪水
步骤说明
DISTINCT Salary去重:相同薪水只保留一个(避免重复影响排名)
ORDER BY Salary DESC按薪水从高到低排序(最高在前)
LIMIT 1 OFFSET 1跳过第 1 行,取 1 行
OFFSET 1:跳过最高薪
LIMIT 1:取接下来的 1 条(即第二高)
. 外层:IFNULL(..., NULL)

sql

编辑

IFNULL( 子查询结果 , NULL )
  • IFNULL(value, default):如果 value 是 NULL,就返回 default
  • 这里 default 也是 NULL,看起来“多此一举”,其实非常关键!
为什么需要 IFNULL

考虑一种情况:

  • 表里只有 1 个员工,或者所有人薪水都一样
  • 那么子查询 LIMIT 1 OFFSET 1 会查不到任何数据
  • 查不到数据 → 返回 NULL
  • 但 SELECT NULL 仍然会返回一行 NULL,而不是“空结果

核心考点与刷题技巧

根据搜索结果显示,以下这些是面试中频繁出现的核心考点,你需要特别注意:

  • NULL值处理:这是面试官的挚爱考点。 搜索结果显示,在过滤条件中,NULL不能直接用 = 或 != 比较,必须使用 IS NULL 或 IS NOT NULL。例如“寻找用户推荐人”一题,referee_id != 2 不会包含 referee_id 为 NULL 的记录。

  • 表连接与连接条件:务必理解清楚不同JOIN的区别。

    • 多表连接:如“学生们参加各科测试的次数”一题,需要先通过CROSS JOIN生成所有学生和所有科目的组合,再LEFT JOIN考试成绩,才能确保不漏掉任何学生-科目组合。

    • 连接条件与过滤ONWHERE的执行顺序不同,会影响结果。例如“平均售价”一题,需要将purchase_date BETWEEN start_date AND end_date这个条件放在ON子句中,而不是WHERE里,否则会错误地过滤掉没有销售记录的产品。

  • 聚合函数与CASE WHENCASE WHENAVG等聚合函数结合,可以巧妙地计算比率。在“确认率”一题中,使用AVG(CASE WHEN action = 'confirmed' THEN 1 ELSE 0 END)可以简洁地得出确认率,并自动处理NULL值。

  • 窗口函数:这是解决复杂问题的利器,常用于排名、累计求和等问题。你需要掌握ROW_NUMBER()RANK()DENSE_RANK()的区别,以及SUM() OVER()的用法。

我的解题思路4步

1.查什么

直接从题意或者输出,知道SELECT什么,有的内容需要处理列入count(xx)as x,或者再内嵌一个函数窗口函数什么的。

2.确表源,

from,以及表之间的关系,jion

from xxx left join ccc 

on xxx.id=ccc.id

3.找条件,

普通查询

where  条件

order by xxx  ESC(升序)/DESC(降序)

LIMIT 数量

分组统计

where

group by xxx

having 过滤条件。

4.完成构建检查。

高频考点速记:

• 分组统计 → GROUP BY + HAVING
• 多表关联 → JOIN ON
• 排名问题 → ROW_NUMBER/RANK
• 连续问题 → LAG/LEAD + 日期计算
• 空值处理 → COALESCE/IFNULL

基础查询模板

1. 简单查询框架

sql

SELECT 字段 
FROM 表 
WHERE 条件 
ORDER BY 排序字段 
LIMIT 数量;

2. 分组统计模板

sql

SELECT 分组字段, 聚合函数(统计字段)
FROM 表 
WHERE 过滤条件 
GROUP BY 分组字段 
HAVING 分组后过滤条件;

3. 内连接模板

sql

SELECT A.字段, B.字段
FROM 表A A
INNER JOIN 表B B ON A.关联字段 = B.关联字段;

4. 左连接模板

sql

SELECT A.字段, B.字段
FROM 表A A
LEFT JOIN 表B B ON A.关联字段 = B.关联字段;

5. 排名前N模板

sql

SELECT 字段
FROM (
    SELECT 字段,
           ROW_NUMBER() OVER (ORDER BY 排序字段 DESC) as rn
    FROM 表
) t
WHERE rn <= N;

6. 部门排名模板

sql

SELECT 字段
FROM (
    SELECT 字段,
           RANK() OVER (PARTITION BY 部门字段 ORDER BY 薪资字段 DESC) as rank
    FROM 表
) t
WHERE rank = 1;

7. 累计统计模板

sql

SELECT 日期字段, 数值字段,
       SUM(数值字段) OVER (ORDER BY 日期字段) as 累计值
FROM 表;

8. 同比环比模板

sql

SELECT 日期, 数值,
       LAG(数值, 1) OVER (ORDER BY 日期) as 上月数值,
       (数值 - LAG(数值, 1) OVER (ORDER BY 日期)) / LAG(数值, 1) OVER (ORDER BY 日期) as 增长率
FROM 表;

9. 连续登录模板

sql

SELECT user_id, COUNT(*) as 连续天数
FROM (
    SELECT user_id, login_date,
           DATE_SUB(login_date, INTERVAL ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) DAY) as flag
    FROM login_records
) t
GROUP BY user_id, flag
HAVING COUNT(*) >= N;

10. 空值替换模板

sql

SELECT COALESCE(字段, 默认值) as 新字段名
FROM 表;

posted @ 2025-11-07 12:48  ycfenxi  阅读(70)  评论(0)    收藏  举报