在Microsoft SQL Server中,如何根据同一列中的值计算中间行。
/-----------------------------------------\
| ID ---------- Event -------- UserID ----|
| 1 ----------- START -------- 000001 ----|
| 2 ----------- START -------- 000002 ----|
| 3 ----------- END -------- 000001 ----|
| 4 ----------- PL -------- 000002 ----|
| 5 ----------- END -------- 000002 ----|
\-----------------------------------------/
考虑UserID
000002,其中有3行,ID为2,4& 5。
根据此link的查询,我可以获得START
和END
时间,但如何在{{1}之间获得行数每个START
END
预期结果
USERID
答案 0 :(得分:4)
SELECT USERID
, sum(CASE WHEN MainT.ID BETWEEN StartT.ID AND EndT.ID THEN 1 ELSE 0 END) AS RowCount
FROM Table1 AS MainT
INNER JOIN Table1 AS StartT
ON MainT.USERID = StartT.USERID AND StartT.event = 'START'
INNER JOIN Table1 AS EndT
ON MainT.USERID = EndT.USERID AND EndT.event = 'END'
GROUP BY USERID
这应该产生所需的输出,具有以下假设:
回应评论:
通常情况下,您无法显示""未被分组的字段的值,因为可能有多个值在播放。这意味着您需要告诉SQL服务器如何使用某种聚合函数处理值。
如果您确定每组只有一个可能的值,您可以作弊并采取min(事件)或max(事件)。这会为您提供组中显示的第一个或最后一个按字母顺序的值。这是有风险的,如果您稍后在该表中包含更多事件,则可能会导致问题。
如果只有几个,您可以按事件类型拆分计数:
sum(CASE WHEN **MainT.event ='EventA' AND** MainT.ID BETWEEN StartT.ID AND EndT.ID THEN 1 ELSE 0 END) AS EventACount,
sum(CASE WHEN **MainT.event ='EventB' AND** MainT.ID BETWEEN StartT.ID AND EndT.ID THEN 1 ELSE 0 END) AS EventBCount,
最后,您可以使用某种列表聚合,连接组中出现的所有事件类型。 This question详细介绍了这一点。
答案 1 :(得分:1)
该方案没有明确定义,您可以在不同的解决方案中看到它。
这将处理简单的用例。
select UserID
,count(*) as cnt
from mytable
这将处理复杂的用例。
select UserID
,min(ID) as from_ID
,max(ID) as to_ID
,count(*) as events
from (select UserID,ID,Event
, count(case when Event in ('START','END') then 1 end) over
(
partition by UserID
order by Id
rows unbounded preceding
)
- case when Event = 'END' then 1 else 0 end as group_seq
from mytable
) t
group by UserID
,group_seq
having min(case when Event = 'START' then 1 end) = 1
order by UserID
,from_id