任何人都可以解释为什么我们不能在group by
子句中使用窗口函数以及为什么只允许SELECT
和ORDER BY
我试图根据row_number()
和SQL Server中的一列对记录进行分组,如下所示:
SELECT Invoice
from table1
group by row_number() over(order by Invoice),Invoice
我收到错误
窗口函数只能出现在SELECT或ORDER BY
中
我可以在SELECT子句中选择此row_number()
,但我想知道为什么我们不能将它分组使用?
答案 0 :(得分:17)
在ANSI规范中定义了窗口函数,以便在处理GROUP BY
,HAVING
,WHERE
之后逻辑执行。
更具体地说,Logical Query Processing flow chart here中的步骤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
有四个不同的逻辑窗口,祝你好运,看看结果如何!另外,如果在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
由于这些都是在SELECT
声明中定义的并且有别名,因此可以轻松实现消除不同级别结果的歧义,例如只需将WHERE NtileForHaving = 1
切换为NtileForGroupBy = 1
答案 1 :(得分:16)
您可以通过将窗口函数放在子查询中来解决这个问题:
select invoice
, rn
from (
select Invoice
, row_number() over(order by Invoice) as rn
from Table1
) as SubQueryAlias
group by
invoice
, rn