[英]SQL Cumulative count on unique Ids
我有如下數據集(按“時間”列排序):
Time ID1 ID2
2:00:00 AM 41 A56E34E0-FBE5-4C58-BDBD-87112E73A978
3:00:00 AM 34 B129798B-485E-41BB-8B9C-39A0E1841109
4:00:00 AM 41 A56E34E0-FBE5-4C58-BDBD-87112E73A978
4:00:00 AM 41 C1C14D08-C155-4857-93E2-3A748AC95C8D
4:00:00 AM 34 A4D389B1-C38F-446A-9336-6AA193D8F0E0
4:00:00 AM 17 C1C14D08-C155-4857-93E2-3A748AC95C8D
如果要按時間和ID1分組的同一ID1之前沒有出現過,我想獲取ID2的累積計數。 因此,對於上述數據集,中間結果可能是:
Time ID1 ID2 IsNewForID1
2:00:00 AM 41 A56E34E0-FBE5-4C58-BDBD-87112E73A978 1
3:00:00 AM 34 B129798B-485E-41BB-8B9C-39A0E1841109 1
4:00:00 AM 41 A56E34E0-FBE5-4C58-BDBD-87112E73A978 0
4:00:00 AM 41 C1C14D08-C155-4857-93E2-3A748AC95C8D 1
4:00:00 AM 34 A4D389B1-C38F-446A-9336-6AA193D8F0E0 1
4:00:00 AM 17 C1C14D08-C155-4857-93E2-3A748AC95C8D 1
並且按時間分組,ID1將是:
Time ID1 Count
2:00:00 AM 41 1
3:00:00 AM 34 1
4:00:00 AM 41 1
4:00:00 AM 34 1
4:00:00 AM 17 1
如何在SQL中執行此操作?
如果您想讓id1
和id2
對首次出現,並加上時間,為什么不只使用group by
? 以下是標准SQL:
select min(time) as time, id1, id2, 1 as count
from dataset
group by id1, id2;
您可以使用Gordon Linoff的建議作為這種解決方案的起點:
SELECT
d.Time,
d.ID1,
d.ID2,
IsNewForID1 = CASE WHEN g.Time IS NULL THEN 0 ELSE 1 END
FROM
YourDataset AS d
LEFT JOIN (
SELECT
Time = MIN(Time),
ID1,
ID2,
FROM
YourDataset
GROUP BY
ID1,
ID2
) AS g ON g.Time = d.Time AND g.ID1 = d.ID1 AND g.ID2 = d.ID2
;
也就是說,派生表包含每個ID1
中ID2
第一個“新”出現,然后將其重新連接到原始數據集以用作參考並分別標記每行。
如果使用的是SQL Server 2005或更高版本,則可以使用窗口MIN重寫以上內容:
SELECT
Time,
ID1,
ID2,
IsNewForID1 = CASE Time
WHEN MIN(Time) OVER (PARTITION BY ID1, ID2) THEN 1
ELSE 0
END
FROM
YourDataset
;
這個想法與以前相同,但是不需要IsNewForID1
表或派生表,因為第一次出現是在細節旁邊獲得的,並且IsNewForID1
列是在同一范圍內計算的。 如果YourDataset
實際上是一個查詢,則此方法尤其可取,因為第一個變體可能會對YourDataset
兩次評估,而第二個變體則避免了。
顯然,要獲得最終結果,您可以采用任一查詢,然后按Time
和ID1
將其進一步分組以采用SUM(IsForNewID1)
:
SELECT
Time,
ID1,
Count = SUM(IsNewForID1)
FROM
(
SELECT
Time,
ID1,
ID2,
IsNewForID1 = CASE Time
WHEN MIN(Time) OVER (PARTITION BY ID1, ID2) THEN 1
ELSE 0
END
FROM
YourDataset
) AS s
;
但是請注意,如果實際上僅需要IsNewForID1
來獲取計數,則可以以其他方式使用Gordon的想法來跳過該中間步驟,如下所示:
SELECT
Time,
ID1,
Count = COUNT(*)
FROM
(
SELECT
Time = MIN(Time),
ID1,
ID2,
FROM
YourDataset
GROUP BY
ID1,
ID2
) AS s
;
本質上,無論您是使用IsNewForID1
還是不使用IsNewForID1
計算它們,結果都是相同的。 但是,就行而言,可能有所不同。 前一種方法可能會返回Count = 0
行。 例如,如果您的示例中的第4行不存在,它將返回以下內容:
Time ID1 Count
---------- --- -----
2:00:00 AM 41 1
3:00:00 AM 34 1
4:00:00 AM 41 0
4:00:00 AM 34 1
4:00:00 AM 17 1
最后一個方法將簡單地忽略計數為0的行,因此4:00:00 AM, 41
如果我們從示例數據中刪除第四行,則在4:00:00 AM, 41
將沒有結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.