SQL REFERENCE

常用 SQL 速查

把高频 SQL 写法整理成可搜索、可复制的参考卡片。这里使用的是通用占位符, 不绑定某一套业务数据。

占位符说明:table_namecolumn_name:param 都需要替换成你当前数据库中的真实表名、字段名和参数。 复制后请根据数据库类型调整日期函数和分页语法。

当前显示 21 / 21 条写法

基础查询

选择需要的字段

从一张表中取出指定列,避免无目的地返回所有字段。

SELECT column_a, column_b
FROM table_name;
基础查询

按条件筛选

只返回满足条件的记录。多个条件可以用 AND 或 OR 连接。

SELECT *
FROM table_name
WHERE status = 'active'
  AND amount >= 100;
基础查询

排序查询结果

使用 ASC 升序或 DESC 降序排列结果。

SELECT column_a, column_b
FROM table_name
ORDER BY column_b DESC, column_a ASC;
去重

去除重复值

返回某个字段或字段组合的不重复结果。

SELECT DISTINCT category
FROM table_name;
去重

统计不重复数量

统计不同用户、客户或订单的数量。

SELECT COUNT(DISTINCT user_id) AS unique_users
FROM table_name;
去重

每个对象只保留最新一条

先为每个对象内部排序,再过滤出序号为 1 的记录。

WITH ranked_rows AS (
  SELECT
    t.*,
    ROW_NUMBER() OVER (
      PARTITION BY entity_id
      ORDER BY updated_at DESC, record_id DESC
    ) AS row_num
  FROM table_name AS t
)
SELECT *
FROM ranked_rows
WHERE row_num = 1;
聚合分析

分组统计

按一个或多个维度汇总记录数、金额或其他指标。

SELECT
  category,
  COUNT(*) AS record_count,
  SUM(amount) AS total_amount
FROM table_name
GROUP BY category;
聚合分析

筛选汇总结果

使用 HAVING 筛选分组后的结果,不能用 WHERE 代替。

SELECT
  category,
  COUNT(*) AS record_count
FROM table_name
GROUP BY category
HAVING COUNT(*) >= 10;
JOIN

只保留两表都能匹配的记录

INNER JOIN 适合只分析存在对应关系的数据。

SELECT
  a.entity_id,
  b.detail_name
FROM table_a AS a
INNER JOIN table_b AS b
  ON a.entity_id = b.entity_id;
JOIN

保留左表全部记录

左表没有匹配记录时,右表字段会显示为 NULL。

SELECT
  a.entity_id,
  b.detail_name
FROM table_a AS a
LEFT JOIN table_b AS b
  ON a.entity_id = b.entity_id;
NULL 与条件

筛选缺失值

判断 NULL 必须使用 IS NULL 或 IS NOT NULL。

SELECT *
FROM table_name
WHERE closed_at IS NULL;
NULL 与条件

为 NULL 提供默认值

COALESCE 从左到右返回第一个非 NULL 值。

SELECT
  entity_id,
  COALESCE(owner_name, '未分配') AS owner_name
FROM table_name;
NULL 与条件

按条件生成分类

把原始数值或状态转换成更容易理解的业务标签。

SELECT
  entity_id,
  CASE
    WHEN amount >= 1000 THEN 'high'
    WHEN amount >= 100 THEN 'medium'
    ELSE 'low'
  END AS amount_level
FROM table_name;
CTE

用 CTE 拆解复杂查询

先命名中间结果,再在后续查询中复用,提升可读性。

WITH filtered_rows AS (
  SELECT *
  FROM table_name
  WHERE status = 'active'
)
SELECT category, COUNT(*) AS record_count
FROM filtered_rows
GROUP BY category;
分页

使用 LIMIT 和 OFFSET 分页

适合数据量较小或需要快速查看第几页结果的场景。

SELECT *
FROM table_name
ORDER BY record_id
LIMIT :page_size OFFSET :offset;
分页

使用游标分页

记录上一页最后一个 ID,避免大 OFFSET 越翻页越慢。

SELECT *
FROM table_name
WHERE record_id > :last_record_id
ORDER BY record_id ASC
LIMIT :page_size;
排名

生成连续序号

ROW_NUMBER 为每一行生成唯一序号,即使并列也不会重复。

SELECT
  entity_id,
  score,
  ROW_NUMBER() OVER (ORDER BY score DESC, entity_id) AS row_num
FROM table_name;
排名

处理并列排名

RANK 会跳号,DENSE_RANK 不跳号;两者都会让并列记录获得相同名次。

SELECT
  entity_id,
  score,
  RANK() OVER (ORDER BY score DESC) AS rank_num,
  DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank_num
FROM table_name;
排名

取每组排名前 N 条

先按分组生成窗口排名,再在外层筛选名次。

WITH ranked_rows AS (
  SELECT
    group_name,
    entity_id,
    score,
    ROW_NUMBER() OVER (
      PARTITION BY group_name
      ORDER BY score DESC, entity_id
    ) AS row_num
  FROM table_name
)
SELECT *
FROM ranked_rows
WHERE row_num <= 3;
日期

筛选一个完整日期范围

使用左闭右开区间,避免结束日期带时间时遗漏或重复数据。

SELECT *
FROM table_name
WHERE event_time >= :start_time
  AND event_time < :next_period_start;
日期

按日期粒度汇总

先把时间转换成日、周或月,再进行分组统计。

SELECT
  date_column AS period,
  COUNT(*) AS record_count
FROM table_name
GROUP BY date_column
ORDER BY period;