This is my code:
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;
On this page of BOL, Microsoft says that:
If PARTITION BY is not specified, the function treats all rows of the query result set as a single group.
So based on my understanding, the last SELECT
statement will give me the following result. Since all records are considered as in one single group, right?
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
But the actual result is:
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
Anyone can help to explain why? Thanks.
It gives a running total (this functionality was not implemented in SQL Server until version 2012.)
The
ORDER BY
defines the window to be aggregated withUNBOUNDED PRECEDING
andCURRENT ROW
as the default when not specified. SQL Server defaults to the less well performingRANGE
option rather thanROWS
.They have different semantics in the case of ties in that the window for the
RANGE
version includes not just the current row (and preceding rows) but also any additional tied rows with the same value ofa
as the current row. This can be seen in the number of rows counted by each in the results below.Returns
To achieve the result that you were expecting to get omit both the
PARTITION BY
andORDER BY
and use an emptyOVER()
clause (also shown above).