web-dev-qa-db-ja.com

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

これは私のコードです:

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;

このBOLのページ では、Microsoftは次のように述べています。

PARTITION BYが指定されていない場合、関数はクエリ結果セットのすべての行を1つのグループとして扱います。

したがって、私の理解に基づくと、最後のSELECTステートメントは次の結果をもたらします。すべてのレコードは1つの単一グループと見なされるので、そうですか?

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

誰もが理由を説明するのを手伝ってくれる?ありがとう。

12
Just a learner

それは現在までの合計を示します(この機能は バージョン2012 になるまでSQL Serverに実装されませんでした。)

_ORDER BY_は、指定されない場合のデフォルトとして、_UNBOUNDED PRECEDING_および_CURRENT ROW_で集約されるウィンドウを定義します。 SQL Serverのデフォルトは、RANGEではなく パフォーマンスが低いROWSオプションです。

RANGEバージョンのウィンドウには、現在の行(およびその前の行)だけでなく、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
_

あなたが除外することを期待していた結果を達成するためにboth_PARTITION BY_および_ORDER BY_を使用し、空のOVER()句(上記にも示されています)。

29
Martin Smith