我有一个包含以下行的表:
MsgID | DateTime | State | TimeDiff
---------------------------------------------
387 | 2014-09-06 21:06:27 | 2 | 43
387 | 2014-09-06 21:06:28 | 3 | 44
212 | 2014-09-06 22:16:27 | 1 | 0
212 | 2014-09-06 22:16:38 | 3 | 11
532 | 2014-09-06 23:26:27 | 1 | 0
532 | 2014-09-06 23:27:27 | 3 | 60
532 | 2014-09-06 23:27:28 | 2 | 61
215 | 2014-09-06 23:46:27 | 1 | 0
212 | 2014-09-07 22:16:27 | 1 | 0
212 | 2014-09-07 22:16:37 | 2 | 10
212 | 2014-09-07 22:16:38 | 3 | 11
我想像这样合并这些行:
MsgID | State 1 | State 2 | State 3 |
-------------------------------------------------------------------------
212 | 2014-09-06 22:16:27 | null | 2014-09-06 22:16:38 |
532 | 2014-09-06 23:26:27 | 2014-09-06 23:27:28 | 2014-09-06 23:27:27 |
215 | 2014-09-06 23:46:27 | null | null |
212 | 2014-09-07 22:16:27 | 2014-09-07 22:16:37 | 2014-09-07 22:16:38 |
在此示例中,MsgID = 387的行被忽略,因为它们没有开始条件(状态1)。
我不知道该如何解决。
答案 0 :(得分:2)
您可以在如下查询中使用PIVOT语句。
请注意,您必须熟悉 PIVOT 语法。
最里面的查询用于限定消息ID,以便不占用MsgId(例如387)。
上面带有row_number()
的查询是为了帮助识别差距。这是gaps-and-islands类型问题的常见解决方案。查看有关缺口和孤岛的有用链接 here
select
MsgID,
State1= [1],
State2= [2],
State3=[3]
from
(
select
t1.MsgID,
t1.DateTime,
T1.State,
r=row_number() over ( order by t1.[DateTime])- row_number() over( partition by t1.MsgID order by t1.[Datetime])
from t t1
join
(
select MsgId
from t
group by MsgID
having min(State)=1
) t2
on t1.MsgId=t2.MsgId
) src
PIVOT
(
max(DateTime) for State in ([1],[2],[3])
)p
答案 1 :(得分:1)
您可以使用差异row_numbers
并进行有条件的聚合:
select msgid, max(case when state = 1 then datetime end) state1,
max(case when state = 2 then datetime end) state2,
max(case when state = 3 then datetime end) state3
from (select *, row_number() over (partition by msgid order by [datetime]) seq1,
row_number() over (partition by msgid, cast(datetime as date) order by datetime) seq2
from table t
where exists (select 1 from table t1 where t1.msgid = t.msgid and t1.state = 1)
) t
group by msgid, (seq1-seq2);
答案 2 :(得分:0)
我不认为这是一个孤岛问题。按消息ID和日期进行简单汇总可用于您的示例数据:
select msgid,
max(case when state = 1 then datetime end) as state1,
max(case when state = 2 then datetime end) as state2,
max(case when state = 3 then datetime end) as state3
from t
group by msgid, cast(datetime as date)
having min(t.state) = 1;
注意:这假定您可能具有的最小状态为“ 1”。否则,您可以使用:
having sum(case when t.state = 1 then 1 else 0 end) > 0;