T-SQL(SQL Server 2017 Community Edition以降)で順序付けられた観測値(行)のカウント(一意および合計)の実行比率をコーディングする方法に関するアイデアはありますか?
必然的に順序付けられるデータセットが与えられた場合(例:日付でインデックス付け/順序付けされた時系列):
CREATE TABLE #x (dt DATE, Name VARCHAR(MAX));
INSERT INTO #x VALUES
('2012-01-01', 'a'),('2012-01-02', 'b'),('2012-01-03', 'c'),
('2012-01-04', 'a'),('2012-01-05', 'b'),('2012-01-06', 'd'),
('2012-01-07', 'a'),('2012-01-08', 'b'),('2012-01-09', 'e'),('2012-01-10', 'e');
したがって、列Dt
とNames
が与えられた場合、以下の出力Ratio
が必要です。わかりやすくするために、現在までの一意の名前をカウントする出力列UCnt
(つまり、制限された実行カウント)と、現在までのすべての名前をカウントする(つまり、単純な実行カウント)TCnt
も含めました。出力Ratio
フィールドは、2つの実行比率です。
Dt Name UCnt TCnt Ratio
2012-01-01 a 1 1 1.000
2012-01-02 b 2 2 1.000
2012-01-03 c 3 3 1.000
2012-01-04 a 3 4 0.750
2012-01-05 b 3 5 0.600
2012-01-06 d 4 6 0.666
2012-01-07 a 4 7 0.571
2012-01-08 b 4 8 0.500
2012-01-09 e 5 9 0.555
2012-01-10 e 5 10 0.500
Lamakに感謝します。 OUTER APPLY
2時間以上実行されました(約100万行)。私はそれを殺さなければなりませんでした。これが同じサイズのテーブルで約30秒かかる私のソリューションです。
WITH y AS (-- count dupped Names and each observation
SELECT dt, Name,
UCnt_=COUNT(*) OVER (PARTITION BY Name ORDER BY Dt),
TCnt=ROW_NUMBER() OVER (ORDER BY Dt)
FROM #x
),
z AS (-- count unique Names only
SELECT *,
UCnt=SUM(CASE WHEN UCnt_>1 THEN 0 ELSE 1 END) OVER (ORDER BY Dt)
FROM y
)
SELECT Dt, Name, UCnt_, UCnt, TCnt, Ratio=UCnt/1.0/TCnt
FROM z
ORDER BY Dt
出力:
Dt Name UCnt_ UCnt TCnt Ratio
2012-01-01 a 1 1 1 1.000
2012-01-02 b 1 2 2 1.000
2012-01-03 c 1 3 3 1.000
2012-01-04 a 2 3 4 0.750
2012-01-05 b 2 3 5 0.600
2012-01-06 d 1 4 6 0.666
2012-01-07 a 3 4 7 0.571
2012-01-08 b 3 4 8 0.500
2012-01-09 e 1 5 9 0.555
2012-01-10 e 2 5 10 0.500
OUTER APPLY
とROW_NUMBER
の組み合わせでうまくいくようです。
WITH CTE AS
(
SELECT *,
Tot_Cnt = ROW_NUMBER() OVER(ORDER BY dt)
FROM #x
)
SELECT A.dt,
A.[Name],
B.Unq_Cnt,
A.Tot_Cnt,
Ratio_of_Cnts = CONVERT(NUMERIC(10,4),B.Unq_Cnt)/A.Tot_Cnt
FROM CTE A
OUTER APPLY (SELECT Unq_Cnt = COUNT(DISTINCT [Name])
FROM CTE
WHERE dt <= A.dt) B
;
これのデモ です。