3

我有一个表,其中包括以下列和数据:

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

我想在数据列中对“d”的序列进行分组,并在序列的末尾使用“@”。

这可以通过实例列进行分组,这是一个单独的数据流,但是流中可以有多个序列。

如果在同一实例中没有数据列,例如,在该实例的最后一个数据之后 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 秒延迟的数据),(instance) 是原始表中的实例 ID,(lastdata)是序列中的最后一个数据值,(dtime) 是最后一个数据值的日期时间值。

4

1 回答 1

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
于 2012-10-22T20:04:04.017 回答