我正在尝试从数据中的现有记录创建子记录聚合。 以此示例数据为例:
Index Date Action
1 1/1/2015 Working
2 1/2/2015 Working
3 1/3/2015 Working
4 1/4/2015 Escalated
5 1/5/2015 Done
6 1/6/2015 Working
7 1/7/2015 Done
8 1/8/2015 Working
9 1/9/2015 Working
10 1/10/2015 Working
11 1/11/2015 Escalated
12 1/12/2015 Done
13 1/13/2015 Done
14 1/14/2015 Working
我希望能够创建这些数据:
Record DateBegin DateEnd #Actions #Escalations
A 1/1/2015 1/5/2015 5 1
B 1/6/2015 1/7/2015 2 0
C 1/8/2015 1/12/2015 5 1
D 1/13/2015 1/13/2015 1 0
E 1/14/2015 null 1 0
基本上,逻辑是当Action值='Done'时子记录结束,并且新的子记录在任何后续动作(以及第一个动作)上开始。 我正在使用SQL Server 2008.感谢您的帮助!
答案 0 :(得分:0)
这是一张设计糟糕的桌子;应该有一个TaskID来识别特定任务(一旦有人在前一个任务完成之前启动任务,这个结构将变得无法使用)。
我会:
使用Index,Date,Action和TaskID创建临时表
写一个游标来迭代旧表,按索引排序。有一个局部变量CurrentTaskID(初始化为1)。对于每个读取记录,将Index,Date,Action和CurrentTaskID写入新表。在每次写入之后,查看Action - 如果它='DONE'然后递增CurrentTaskID
在临时表上写一个类似的查询:
SELECT min(a.date),max(a.date),count(*)
,(SELECT count(*)
FROM MyTempTable b WHERE b.TaskID = a.TaskID AND b.Action ='Escalated')
FROM MyTempTable a GROUP BY a.TaskID
答案 1 :(得分:0)
有趣的问题。试试这个,应该有用。
;with dones as (
select
nn = ROW_NUMBER() over(order by [Date])
,*
from YourTable
where action = 'Done'
), ranges as (
select
[Record] = CHAR(ASCII('A') - 1 + ISNULL(d2.nn, d1.nn + 1)) -- A,B,C,... - after 255 will give NULL
,dtFrom = d1.[Date]
,dtTo = d2.[Date]
from dones d1
full join dones d2 on d1.nn = d2.nn + 1
)
select
dones.[Record]
,DateBegin = MIN(tt.[date])
,DateEnd = dones.dtTo
,[#Actions] = COUNT(tt.*)
,[#Escalations] = SUM(case when tt.Action = 'Escalated' then 1 else 0 end)
from YourTable tt
inner join dones
on (dones.dtFrom is null or tt.[date] > dones.dtFrom )
and (dones.dtTo is null or tt.[date] <= dones.dtFrom)
group by dones.[Record], dones.dtTo;
答案 2 :(得分:0)
您可以通过计算每条记录前done
条记录的数量来分配分组参数。其余的只是聚合,虽然为每个组分配一个字母似乎是不必要的复杂化:
select grp as record, min(Date) as DateBegin,
max(case when Action = 'Done' then Date end) as DateEnd,
count(*) as NumActions,
sum(case when Action = 'Escalation' then 1 else 0 end) as NumEscalations
from (select e.*, coalesce(e2.grp, 0) as grp
from example e outer apply
(select count(*) as grp
from example e2
where e2.id < e.id and e2.Action = 'Done'
) e2
) e
group by grp;
此查询在SQL Server 2012+中更简单(也更高效),它支持累积总和。
编辑:
我注意到我使用子查询,但这不是必需的。这可以写成:
select coalesce(grp, 0) as record, min(Date) as DateBegin,
max(case when Action = 'Done' then Date end) as DateEnd,
count(*) as NumActions,
sum(case when Action = 'Escalation' then 1 else 0 end) as NumEscalations
from example e outer apply
(select count(*) as grp
from example e2
where e2.id < e.id and e2.Action = 'Done'
) e2
group by e2.grp