我有一个表,其中包含以下列和数据:
id dtime instance data dtype
1 2012-10-22 10000 d 1
2 2012-10-22 10000 d 1
..
7 2012-10-22 10004 d 1
..
15 2012-10-22 10000 @ 1
16 2012-10-22 10004 d 1
17 2012-10-22 10000 d 1
我想在数据列中对's'的序列进行分组,序列末尾有'@'。
这可以通过实例列进行分组来完成,实例列是一个单独的数据流,但是流中可以有多个序列。
如果在同一个实例中没有数据列,例如,在该实例的最后一个数据之后3秒并且在该间隔内没有找到“@”,我也想结束一个序列。
我已经设法使用游标和while循环来完成这项工作,这对于具有1000行的表来说相当不错,但是这个查询最终会在更多的行上使用,而这两种方法大约需要一分钟数据集只有3-5000行。
在这个网站和其他人看来,似乎基于集合的逻辑可能是要走的路,但是如果没有在每一行上的某种循环将其与其他行进行比较,我认为没办法做我需要的工作。建立'序列'。
如果有人可以提供帮助,或者指出我可能的方向,我们将不胜感激。 :)
理想情况下,我希望以下列格式输出数据:
datacount实例lastdata dtime
20 10000 @ 2012-10-22
19 10000 d 2012-10-22
22 10004 @ 2012-10-22
20 10022 @ 2012-10-22
其中(datacount)是'序列'中行数的计数(这是导致'@'或3秒延迟的数据),(实例)是原始表中的实例ID, (lastdata)是序列中的最后一个数据值,(dtime)是最后一个数据值的日期时间值。
答案 0 :(得分:1)
让我告诉你如何为最后的'@'做这个。时差遵循类似的想法。关键的想法是在当前行之后获得下一个'@'。为此,您需要一个相关的子查询。之后,您可以通过以下方式进行分组:
select groupid, count(*) as NumInSeq, max(dtime) as LastDateTime
from (select t.*,
(select min(t2.id) from t t2 where t2.id > t.id and t2.data = '@'
) as groupid
from t
) t
group by groupid
处理时间序列有点复杂。它是这样的:
select groupid, count(*) as NumInSeq, max(dtime) as LastDateTime,
(case when sum(case when data = '@' then 1 else 0 end) > 0 then '@' else 'd' end) as FinalData
from (select t.*,
(select min(t2.id)
from t t2
where t2.id > t.id and
(t2.data = '@' or UNIX_TIMESTAMP(t2.dtime) - UNIX_TIMESTAMP(t.dtime) < 3
) as groupid
from t
) t
group by groupid