PARTITION BY多列语法用逗号分隔列名,如PARTITION BY dept, year,不加括号;它定义窗口边界但不排序,排序需单独写ORDER BY;与GROUP BY根本区别在于保留原行数而非聚合压缩。

PARTITION BY 多列语法怎么写
直接用逗号分隔列名,和 GROUP BY 的写法一致,但语义不同:它不聚合行,而是定义窗口的边界。比如想按部门和年份分别计算每个员工的薪资排名,就得同时分区这两列。
常见错误是套用 GROUP BY 思维,以为要加 ORDER BY 才能生效——其实 PARTITION BY 本身不排序,ORDER BY 是单独跟在 OVER 里的子句,控制窗口内计算顺序。
-
PARTITION BY dept, year正确;PARTITION BY (dept, year)错误(括号会报语法错) - 列顺序影响结果:如果先写
year再写dept,那每个“年份+部门”组合才是独立窗口,和反过来逻辑等价,但可读性建议按业务主次排 - 允许混合列类型:可以是字段名、表达式(如
YEAR(hire_date)),甚至常量(PARTITION BY 1表示全表一个窗口)
多列 PARTITION BY 和 GROUP BY 的根本区别
很多人卡在这儿:为什么不能直接用 GROUP BY dept, year 配合 SUM(salary)?因为 GROUP BY 会压缩行数,而 PARTITION BY 保留原始行结构,只是给每行打上“当前分区的统计值”。比如你有一张员工明细表,想在每行显示“本部门本年度平均薪资”,就必须用窗口函数。
-
GROUP BY dept, year→ 输出 N 行(N = 唯一分组数) -
PARTITION BY dept, year→ 输出原表所有行,每行附带对应分组的AVG(salary) OVER(...) - 性能上:多列
PARTITION BY通常比单列慢,尤其当组合基数高(如用户ID+时间戳)时,数据库要建更多临时分区结构
容易被忽略的 NULL 处理问题
如果分区列中有 NULL,不同数据库行为不一致:PostgreSQL 和 SQL Server 把所有 NULL 当作同一组;MySQL 8.0+ 默认也如此,但可通过 SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH' 影响字符串比较——实际中更稳妥的做法是显式处理。
- 用
COALESCE(dept, 'UNKNOWN')替换NULL,避免意外合并 - 检查执行计划:如果分区列未建索引,且数据量大,
PARTITION BY可能触发全表扫描,即使只查几行 - 注意字符集:比如
dept = 'SALES'和dept = 'sales'在大小写敏感排序规则下属于不同分区
真实场景下的典型写法示例
假设要查每个部门每年的销售额,并标记当年部门内销售额 Top 3 的订单:
SELECT
order_id,
dept,
YEAR(order_date) AS year,
amount,
ROW_NUMBER() OVER (
PARTITION BY dept, YEAR(order_date)
ORDER BY amount DESC
) AS rn
FROM orders
WHERE rn <= 3;注意:这个 WHERE rn 不能直接写,因为窗口函数在 <code>WHERE 之后执行——得套一层子查询或 CTE。真正可运行的是:
SELECT * FROM (
SELECT
order_id,
dept,
YEAR(order_date) AS year,
amount,
ROW_NUMBER() OVER (
PARTITION BY dept, YEAR(order_date)
ORDER BY amount DESC
) AS rn
FROM orders
) t
WHERE rn <= 3;多列 PARTITION BY 看似简单,但一旦涉及 NULL、排序稳定性、执行计划,就很容易跑出意料之外的结果。上线前务必用小数据集验证分区边界是否符合业务预期。

















