给出一个存储每个项目的每个修订版的表。
例如:
+--------+----------+---------------+--------+---------------------+
| ItemId | Revision | PreviousState | State | DateChanged |
+--------+----------+---------------+--------+---------------------+
| 1 | 1 | NULL | New | 2014-11-13 10:00:00 |
| 1 | 2 | New | Active | 2014-11-15 10:00:00 |
| 1 | 3 | Active | New | 2014-11-17 10:00:00 |
| 1 | 4 | New | Active | 2014-11-19 10:00:00 |
| 1 | 5 | New | Active | 2014-11-20 10:00:00 |
| 1 | 6 | Active | Closed | 2014-11-22 10:00:00 |
| 2 | 1 | NULL | New | 2014-11-13 10:00:00 |
| 2 | 2 | New | Active | 2014-11-16 10:00:00 |
| 2 | 3 | Active | Closed | 2014-11-17 10:00:00 |
| 2 | 4 | Closed | Active | 2014-11-19 10:00:00 |
| 2 | 5 | Active | Closed | 2014-11-21 10:00:00 |
+--------+----------+---------------+--------+---------------------+
我需要计算每个州每个项目的天数('关闭')。
结果应该是这样的:
+--------+-----+--------+
| ItemId | New | Active |
+--------+-----+--------+
| 1 | 4 | 5 |
| 2 | 3 | 3 |
+--------+-----+--------+
我尝试使用两种方法 - GROUP BY
和嵌套游标。
使用游标(尤其是嵌套游标)是一种不好的做法。而且非常慢。
GROUP BY
也没有工作,因为没有严格的州令(New - > Active - > Closed)。它可能是混乱的新 - >有效 - >已关闭 - >有效 - >已关闭 - >新 - >闭合。
在没有迭代所有记录和比较状态的情况下,我没有看到任何其他计算方法。
有没有解决方案?
提前致谢。
答案 0 :(得分:1)
这为您提供了相同的结果,格式略有不同(但如果您需要完全相同的结果集,则可以轻松找到PIVOT
个解决方案):
declare @t table (ItemId int,Revision int,State varchar(19),DateChanged datetime2)
insert into @t(ItemId,Revision,State,DateChanged) values
(1,1,'New', '2014-11-13T10:00:00'),
(1,2,'Active','2014-11-15T10:00:00'),
(1,3,'New', '2014-11-17T10:00:00'),
(1,4,'Active','2014-11-19T10:00:00'),
(1,5,'Active','2014-11-20T10:00:00'),
(1,6,'Closed','2014-11-22T10:00:00'),
(2,1,'New', '2014-11-13T10:00:00'),
(2,2,'Active','2014-11-16T10:00:00'),
(2,3,'Closed','2014-11-17T10:00:00'),
(2,4,'Active','2014-11-19T10:00:00'),
(2,5,'Closed','2014-11-21T10:00:00')
;With Joined as (
select t1.ItemId,t1.State,DATEDIFF(day,t1.DateChanged,t2.DateChanged) as Days
from
@t t1
inner join
@t t2
on
t1.ItemId = t2.ItemId and
t1.Revision = t2.Revision -1
)
select ItemId,State,SUM(Days)
from Joined
where State <> 'Closed'
group by ItemId,State
结果:
ItemId State
----------- ------------------- -----------
1 Active 5
1 New 4
2 Active 3
2 New 3
请注意,我忽略了您问题中的PreviousState
列,而是构建Joined
,因为当 下一个时真正重要的是强>国家生效。
由于您未在问题中描述这些问题而未处理的问题:1)如果当前最终状态不是Closed
该怎么办 - 即我们是否忽略它,或者直到今天?,以及2)如果每个DateChanged
的时间不相同怎么办 - 我们是否必须处理部分日子?
答案 1 :(得分:0)
我个人喜欢[Damien_The_Unbeliever]的CTE,我需要经常使用它们。使用内连接我基本上做同样的事情,在结果周围添加一个pivot包装器来获得你想要的东西:(替换@t作为你的真实表名)
SELECT ItemId , [New],[Active]
FROM
(
SELECT
ItemId , LASTSTATE, DATEDIFF(D, LASTDATE, DateChanged) AS D
FROM
@T AS T
INNER JOIN
(SELECT
ItemId as ItemLink,
Revision + 1 AS RevLink ,
DateChanged AS LASTDATE ,
State AS LASTSTATE from @t
) AS L ON T.ItemId = L.ItemLink AND T.Revision = L.RevLink
) AS P PIVOT ( SUM(D) FOR LASTSTATE IN ([New],[Active],[Closed])) AS DATA