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ループを使用してこれを正確に行うことができました。これは、数千行のテーブルで適切に機能しましたが、このクエリは最終的にははるかに多くの行で使用され、これら2つの方法はデータセットだけで約1分かかります。 3-5000行。

このWebサイトや他のWebサイトを読むと、セットベースのロジックが進むべき道のようですが、各行で何らかのループを実行してビルドするために必要なことを実行する方法は考えられません。 「シーケンス」。

誰かが助けてくれるか、何かできることの方向に私を向けてくれるなら、それは大いにありがたいです。:)

理想的には、データを次の形式で出力したいと思います。

datacountインスタンスlastdatadtime

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 に答える