使用 ROW_NUMBER() 窗口函数选择行

Mat*_*hew 1 sql snowflake-cloud-data-platform

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

SQL 编译错误:窗口函数 [ROW_NUMBER() OVER (ORDER BY EMPLOYEE.SALARY_GRADE_ID ASC NULLS 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;
Run Code Online (Sandbox Code Playgroud)

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

Nic*_*ick 6

您的问题是它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
Run Code Online (Sandbox Code Playgroud)

请注意,您应该使用显式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
Run Code Online (Sandbox Code Playgroud)

  • @LiamClarke 是的!它使得编写此类查询变得*很多*容易。 (3认同)
  • 天啊!这个不错。我没有意识到这个方便的小窍门。谢谢!我一般都是用写出来的。 (3认同)
  • 哦,QUALIFY 是 SQL 的一个很好的扩展。 (2认同)

Lia*_*rke 5

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;
Run Code Online (Sandbox Code Playgroud)

我还将连接谓词移至 FROM 子句中,作为最佳实践,以避免在谓词被Employee.Salary_Grade_Id = Salary_Grades.Grade_Id错误删除时发生意外的笛卡尔连接。

  • 这是标准 SQL 的方法。 (2认同)