使用ROW_NUMBER()窗口功能选择行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用ROW_NUMBER()窗口功能选择行相关的知识,希望对你有一定的参考价值。

我目前正在为工作中的流程编写查询。我试图通过应用ROW_NUMBER()函数来获取特定行,然后根据其行位置选择行。但是,我得到以下错误

SQL编译错误:窗口函数[ROW_NUMBER()OVER(ORDER BY EMPLOYEE.SALARY_GRADE_ID ASCNULLS LAST)]出现在SELECT,QUALIFY和ORDER BY子句的外部。

查询:

SELECT Employee.Salary_Grade_Id, SUM(Salary_Grades.Grade_Amount) AS total, ROW_NUMBER() OVER(ORDER 
BY Employee.Salary_Grade_Id) AS rowCol FROM Employee, Salary_Grades 
WHERE (Employee.Salary_Grade_Id = Salary_Grades.Grade_Id AND rowCol = 1) GROUP BY 
Employee.Salary_Grade_Id;

没有意义的是,当我删除AND rowCol = 1时,查询没有错误。但是有了它,我得到了错误。这是怎么回事?

答案

您的问题是rowCol是窗口函数(ROW_NUMBER())的别名,它们不能出现在WHERE子句中。您可以改用QUALIFY子句:

SELECT Employee.Salary_Grade_Id, 
       SUM(Salary_Grades.Grade_Amount) AS total, 
       ROW_NUMBER() OVER(ORDER BY Employee.Salary_Grade_Id) AS rowCol 
FROM Employee, Salary_Grades 
WHERE (Employee.Salary_Grade_Id = Salary_Grades.Grade_Id)
GROUP BY Employee.Salary_Grade_Id
QUALIFY rowCol = 1

注意,您应该使用显式的JOIN语法并将查询重写为

SELECT Employee.Salary_Grade_Id, 
       SUM(Salary_Grades.Grade_Amount) AS total, 
       ROW_NUMBER() OVER(ORDER BY Employee.Salary_Grade_Id) AS rowCol 
FROM Employee
JOIN Salary_Grades ON Employee.Salary_Grade_Id = Salary_Grades.Grade_Id
GROUP BY Employee.Salary_Grade_Id
QUALIFY rowCol = 1
另一答案

WHERE子句在开窗口之前应用,因此您不能在WHERE子句中引用开窗口函数。您需要使用子查询:

SELECT 
    grade_id, 
    sum(grade_amount) as total
FROM (
    SELECT
        Employee.Salary_Grade_Id as grade_id, 
        Salary_Grades.Grade_Amount AS grade_amount, 
        ROW_NUMBER() OVER(ORDER BY Employee.Salary_Grade_Id) AS rowCol 
    FROM Employee JOIN Salary_Grades ON Employee.Salary_Grade_Id = Salary_Grades.Grade_Id) x
WHERE  rowCol = 1
GROUP BY grade_id;

我还把您的连接谓词上移到FROM子句中,这是避免错误地删除谓词Employee.Salary_Grade_Id = Salary_Grades.Grade_Id的意外笛卡尔联接的最佳实践。

以上是关于使用ROW_NUMBER()窗口功能选择行的主要内容,如果未能解决你的问题,请参考以下文章

为啥将 ROW_NUMBER 定义为窗口函数?

窗口函数 ROW_NUMBER

MySQL5.7实现ROW_NUMBER窗口函数功能SQL

前 MariaDB 版本中的 Row_Number() 窗口函数

开窗函数和row_number()

如何选择另一个选择查询结果的第 10、20、30 ... 行