窗口函数只能出现在SELECT或ORDER BY子句中

Mar*_*ari 19 sql sql-server

任何人都可以解释为什么我们不能在group by子句中使用窗口函数以及为什么它只允许在SELECT和中使用ORDER BY

我试图根据row_number()SQL Server中的一个列对记录进行分组,如下所示:

SELECT Invoice
from table1
group by row_number() over(order by Invoice),Invoice
Run Code Online (Sandbox Code Playgroud)

我收到了一个错误

窗口函数只能出现在SELECT或ORDER BY中

我可以row_number()在SELECT子句中选择它,但我想知道为什么我们不能使用它分组?

Mar*_*ith 18

窗口函数在ANSI规范定义的处理之后执行逻辑GROUP BY,HAVING,WHERE.

更具体地说,这里逻辑查询处理流程图中的步骤5.1和6允许它们.

我想他们可以这样来定义它的另一种方式,并允许GROUP BY,WHERE,HAVING使用窗口函数与窗口是合乎逻辑的结果设定在该阶段的开始,但假设他们有和我们被允许构造查询如

SELECT a, 
       b, 
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect
  FROM YourTable
  WHERE NTILE(2) OVER (PARTITION BY a ORDER BY b) > 1
  GROUP BY a, 
           b, 
           NTILE(2) OVER (PARTITION BY a ORDER BY b)
  HAVING NTILE(2) OVER (PARTITION BY a ORDER BY b) = 1
Run Code Online (Sandbox Code Playgroud)

有四个不同的逻辑窗口可以运气好运,看看结果会是什么!还有,如果在HAVING你真正想要通过GROUP BY上面的级别的表达式过滤而不是行的窗口是后面的结果GROUP BY

CTE版本更详细,但更明确,更容易理解.

WITH T1 AS
(
SELECT a, 
       b, 
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForWhere
  FROM YourTable
), T2 AS
(
SELECT a,
       b,
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForGroupBy
FROM T1
WHERE NtileForWhere > 1
), T3 AS
(
SELECT a,
       b,
       NtileForGroupBy,
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForHaving
FROM T2
GROUP BY a,b, NtileForGroupBy
)
SELECT a,
       b,
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect
FROM T3
WHERE NtileForHaving = 1
Run Code Online (Sandbox Code Playgroud)

由于这些都是在SELECT语句中定义的并且是别名的,因此很容易实现消除不同级别结果的歧义,例如简单地通过切换WHERE NtileForHaving = 1NtileForGroupBy = 1

  • 现在,逻辑查询处理流程图..LINK已损坏 (2认同)
  • @Alex - 我认为这只是一个错误。该网站列出了同一作者 (Itzik Ben Gan) 的新订单,该订单纠正了这一问题。http://porterwebsites.com/sql-server-logic-query/ (2认同)

And*_*mar 16

您可以通过将窗口函数放在子查询中来解决此问题:

select  invoice
,       rn
from    (
        select  Invoice
        ,       row_number() over(order by Invoice) as rn
        from    Table1
        ) as SubQueryAlias
group by
        invoice
,       rn
Run Code Online (Sandbox Code Playgroud)