我有如下数据集(按时间列排序):
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中执行此操作?
答案 0 :(得分:1)
如果您希望第一次出现id1
和id2
对,并且为什么不使用group by
?以下是标准SQL:
select min(time) as time, id1, id2, 1 as count
from dataset
group by id1, id2;
答案 1 :(得分:-1)
您可以使用Gordon Linoff's suggestion作为此类解决方案的起点:
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
;
也就是说,派生表包含第一个"新",每个ID2
出现ID1
,并将它连接回原始数据集以用作参考和标记每一行分别。
如果您使用的是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
列是在同一范围内计算的。如果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
还是使用Count = 0
计算结果,结果都是相同的。但是,就行而言,可能存在差异。前一种方法可能会返回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
行。例如,如果您的示例中的第4行不存在,它将返回以下内容:
4:00:00 AM, 41
最后一个方法只会省略计数为0的行,因此如果我们从示例数据中删除第四行,则{{1}}将没有结果。