TSQL OVER子句:COUNT(*)OVER(ORDER BY a)

时间:2013-02-13 18:11:40

标签: sql sql-server tsql sql-server-2012 window-functions

这是我的代码:

USE [tempdb];
GO

IF OBJECT_ID(N'dbo.t') IS NOT NULL
BEGIN
    DROP TABLE dbo.t
END
GO

CREATE TABLE dbo.t
(
    a NVARCHAR(8),
    b NVARCHAR(8)
);
GO

INSERT t VALUES ('a', 'b');
INSERT t VALUES ('a', 'b');
INSERT t VALUES ('a', 'b');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('e', NULL);
INSERT t VALUES (NULL, NULL);
INSERT t VALUES (NULL, NULL);
INSERT t VALUES (NULL, NULL);
INSERT t VALUES (NULL, NULL);
GO

SELECT  a, b,
    COUNT(*) OVER (ORDER BY a)
FROM    t;

this page of BOL上,微软说:

  

如果未指定PARTITION BY,则该函数会处理该行的所有行   查询结果集作为单个组。

基于我的理解,最后SELECT语句会给我以下结果。由于所有记录都被视为一个组,对吧?

a        b        
-------- -------- -----------
NULL     NULL     12
NULL     NULL     12
NULL     NULL     12
NULL     NULL     12
a        b        12
a        b        12
a        b        12
c        d        12
c        d        12
c        d        12
c        d        12
e        NULL     12

但实际结果是:

a        b        
-------- -------- -----------
NULL     NULL     4
NULL     NULL     4
NULL     NULL     4
NULL     NULL     4
a        b        7
a        b        7
a        b        7
c        d        11
c        d        11
c        d        11
c        d        11
e        NULL     12

任何人都可以帮忙解释原因吗?感谢。

2 个答案:

答案 0 :(得分:29)

它提供了一个运行总计(在version 2012之前,SQL Server中未实现此功能。)

ORDER BY定义了在未指定时将UNBOUNDED PRECEDINGCURRENT ROW聚合为默认值的窗口。 SQL Server默认使用less well performing RANGE选项,而不是ROWS

在绑定的情况下,它们具有不同的语义,因为RANGE版本的窗口不仅包括当前行(和前面的行),还包括具有相同值{{1}的任何其他绑定行}作为当前行。这可以从以下结果中每个计算的行数中看出。

a

返回

SELECT  a, 
        b,
        COUNT(*) OVER (ORDER BY a 
                         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS  [Rows],
        COUNT(*) OVER (ORDER BY a 
                         RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Range],
        COUNT(*) OVER() AS [Over()]
    FROM    t;

为了达到您希望省略 a b Rows Range Over() -------- -------- ----------- ----------- ----------- NULL NULL 1 4 12 NULL NULL 2 4 12 NULL NULL 3 4 12 NULL NULL 4 4 12 a b 5 7 12 a b 6 7 12 a b 7 7 12 c d 8 11 12 c d 9 11 12 c d 10 11 12 c d 11 11 12 e NULL 12 12 12 PARTITION BY并使用空ORDER BY子句(也如上所示)的结果。

答案 1 :(得分:1)

如果未指定ROWS / RANGE但指定了ORDER BY,则将RANGE UNBOUNDED PRECEDING AND CURRENT ROW用作窗口框架的默认值 因此,这意味着什么,让我们集中讨论“无边界的先行和当前行”。这给出了从开始行到当前行的运行总计。 但是,如果您希望有一个总体计数,则还可以指定

“未绑定的前导和未绑定的后继” 这考虑了整个数据集,而Over()只是此操作的快捷方式

    select a,b,
count(*) over(order by a) as [count],
COUNT(*) OVER (ORDER BY a 
                         RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Range],
COUNT(*) OVER (ORDER BY a 
                         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS  [Rows],
COUNT(*) OVER (ORDER BY a 
                         RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED Following) AS [Range_Unbounded_following],
COUNT(*) OVER (ORDER BY a 
                         ROWs BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED Following) AS [Row_Unbounded_following]
,COUNT(*) OVER () AS [Plain_over]
from t 
order by [count]

结果是

a        b        count       Range       Rows        Range_Unbounded_following Row_Unbounded_following Plain_over
-------- -------- ----------- ----------- ----------- ------------------------- ----------------------- -----------
NULL     NULL     4           4           1           12                        12                      12
NULL     NULL     4           4           2           12                        12                      12
NULL     NULL     4           4           3           12                        12                      12
NULL     NULL     4           4           4           12                        12                      12
a        b        7           7           5           12                        12                      12
a        b        7           7           6           12                        12                      12
a        b        7           7           7           12                        12                      12
c        d        11          11          8           12                        12                      12
c        d        11          11          9           12                        12                      12
c        d        11          11          10          12                        12                      12
c        d        11          11          11          12                        12                      12
e        NULL     12          12          12          12                        12                      12