SQL查询中什么情况下用"qualify"替代"where"
需要用 QUALIFY 替代 WHERE 的情况通常是:
- 需要基于窗口函数的结果进行过滤:窗口函数(如 RANK()、ROW_NUMBER()、DENSE_RANK() 等)是在 SELECT 阶段计算的,而 WHERE 子句在查询的早期阶段执行,无法直接引用窗口函数的结果。
- 避免复杂子查询:在不支持 QUALIFY 的数据库中,你可能需要使用子查询或 CTE(公共表表达式)来实现相同的逻辑,而 QUALIFY 提供了更简洁的写法。
示例对比:
使用 WHERE(不适用): 如果你尝试用 WHERE 直接过滤窗口函数的结果,会报错,因为 WHERE 无法识别窗口函数的别名:
SELECT employee_id, department, salary, RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank FROM employees WHERE rank = 1; -- 错误!WHERE 无法引用 rank
使用子查询(替代方案): 在不支持 QUALIFY 的数据库中,你需要用子查询或 CTE:
SELECT * FROM ( SELECT employee_id, department, salary, RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank FROM employees ) t WHERE rank = 1;
使用 QUALIFY(更简洁): 在支持 QUALIFY 的数据库中,可以直接写:
SELECT employee_id, department, salary, RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank FROM employees QUALIFY rank = 1;
4. 什么时候用QUALIFY?
- 当你的查询涉及窗口函数,并且需要根据窗口函数的结果(如排名、累计总和、行号等)来过滤数据时。
- 当你希望简化查询,避免使用嵌套子查询或 CTE。
- 典型场景: 找出每个分组中排名前 N 的记录(如每个部门薪水最高的员工)。 基于窗口函数的结果(如 ROW_NUMBER()、NTILE() 等)筛选特定行。
5. 注意事项
- QUALIFY 的兼容性:并非所有数据库都支持 QUALIFY。它常见于 Teradata、Snowflake 等数据库,但在 PostgreSQL、MySQL、SQL Server 等数据库中不可用。如果你的数据库不支持 QUALIFY,需要使用子查询或 CTE。
- 执行顺序:SQL 的逻辑执行顺序是: FROM 和 JOIN WHERE GROUP BY 和聚合 窗口函数计算 QUALIFY SELECT ORDER BY 因此,QUALIFY 在窗口函数计算之后执行,而 WHERE 在之前。