6

PostgreSQL 9.2 を使用しています。
一部のデバイスがサービスを停止する時間を含むテーブルがあります。

+----------+----------+---------------------+
| event_id |  device  |         time        |
+----------+----------+---------------------+
|        1 | Switch4  | 2013-09-01 00:01:00 |
|        2 | Switch1  | 2013-09-01 00:02:30 |
|        3 | Switch10 | 2013-09-01 00:02:40 |
|        4 | Switch51 | 2013-09-01 03:05:00 |
|        5 | Switch49 | 2013-09-02 13:00:00 |
|        6 | Switch28 | 2013-09-02 13:01:00 |
|        7 | Switch9  | 2013-09-02 13:02:00 |
+----------+----------+---------------------+

次のように、行を +/-3 分の時間差でグループ化する必要があります。

+----------+----------+---------------------+--------+
| event_id |  device  |         time        |  group |
+----------+----------+---------------------+--------+
|        1 | Switch4  | 2013-09-01 00:01:00 |      1 |
|        2 | Switch1  | 2013-09-01 00:02:30 |      1 |
|        3 | Switch10 | 2013-09-01 00:02:40 |      1 |
|        4 | Switch51 | 2013-09-01 03:05:00 |      2 |
|        5 | Switch49 | 2013-09-02 13:00:00 |      3 |
|        6 | Switch28 | 2013-09-02 13:01:00 |      3 |
|        7 | Switch9  | 2013-09-02 13:02:00 |      3 |
+----------+----------+---------------------+--------+

ウィンドウ関数を使って作ってみたのですが、節に

[ 範囲 | ROWS ] BETWEEN frame_start AND frame_end、ここで、frame_start と frame_end は UNBOUNDED PRECEDING 値 PRECEDING CURRENT ROW 値 FOLLOWING UNBOUNDED FOLLOWING のいずれかです。

値は、変数、集約関数、またはウィンドウ関数を含まない整数式でなければなりません

したがって、これを考慮すると、時間間隔を示すことはできません。今、ウィンドウ関数が私の問題を解決できるとは思えません。私たちを手伝ってくれますか?

4

5 に答える 5

5

SQL フィドル

select
    event_id, device, ts,
    floor(extract(epoch from ts) / 180) as group
from t
order by ts

ウィンドウ関数を使用してグループ番号を 1 から始まるシーケンスにすることは可能ですが、必要かどうかはわかりませんが、少なからずコストがかかります。これです

select
    event_id, device, ts,
    dense_rank() over(order by "group") as group
from (
    select
        event_id, device, ts,
        floor(extract(epoch from ts) / 180) as group
    from t
) s
order by ts

timeは予約語です。列名として別のものを選択します。

于 2013-09-13T10:30:22.227 に答える
1

これは、 @Clodoaldoの基本的に良い答えよりもわずかに改善されています。

連続したグループ番号を取得するには:

SELECT event_id, device, ts
      ,dense_rank() OVER (ORDER BY trunc(extract(epoch from ts) / 180)) AS grp
FROM   tbl
ORDER  BY ts
  • ts(部分的に) 予約語の代わりに使用することtimeは良いアドバイスです。したがって、予約語 も使用しないでくださいgroupgrp代わりに使用します。

  • 連番は、サブクエリなしで使用できます。

  • trunc()の代わりに使用しfloor()ます。どちらも良いですtrunc()が、少し速いです。

于 2013-09-13T11:37:51.377 に答える
0

http://www.depesz.com/2010/09/12/how-to-group-messages-into-chats/

ウィンドウを使用する必要があります。教科書の例です

with
  xinterval( val ) as ( select 2 ),
  data( id, t ) as 
  (
    values  

      ( 1000, 1 ),
      ( 1001, 2 ),
      ( 1002, 3 ),

      ( 1000, 7 ),
      ( 1003, 8 )

  ),  
  x( id, t, tx ) as
  (
    select id, t,
      case (t - lag(t) over (order by t)) > xinterval.val
        when true then t when null then t
      end
    from data natural join xinterval
  ),
  xx( id, t, t2 ) as
  (
    select id, t, max(tx) over (order by t) from x
  )
select id, t, text( min(t) over w ) || '-' || text( max(t) over w ) as xperiod
from xx
window w as ( partition by t2 )
order by t
于 2013-09-13T18:04:50.127 に答える