3

2つの異なる(まだ類似している)ウィンドウ関数を使用して、行の時間(マイナス1時間)までの2つの値SUMを計算COUNTしたいと思います 。is_active over user_id+item私の直感はROWSを使用するUNBOUNDED PRECEDINGことでしたが、その方法では時間の経過とともにフィルタリングできません

COUNT(1) OVER(PARTITION BY user_id, item ORDER BY req_time ROWS UNBOUNDED PRECEDING) 
SUM(is_active) OVER(PARTITION BY user-id, item ORDER BY req_time ROWS UNBOUNDED PRECEDING) 

ただし、「1時間前」の間隔係数は考慮されていません。

次のデータを検討してください。

user_id |     req_time       | item  | is_active |  
--------+--------------------+-------------------+---
1   | 2011-01-01 12:00:00|   1   |     0     |
1   | 2011-01-01 12:30:00|   1   |     1     |
1   | 2011-01-01 15:00:00|   1   |     1     |
1   | 2011-01-01 16:00:00|   1   |     0     |
1   | 2011-01-01 16:00:00|   2   |     0     |
1   | 2011-01-01 16:20:00|   2   |     1     |
2   | 2011-02-02 11:00:00|   1   |     1     |
2   | 2011-02-02 13:00:00|   1   |     0     |
1   | 2011-02-02 16:20:00|   1   |     0     |
1   | 2011-02-02 16:30:00|   2   |     0     |

次の結果が期待されます。「値1」はSUM(is_active)で、「値2」はCOUNT(1)です。

user_id |     req_time       | item  | value 1 | value 2 |  
--------+--------------------+-----------------+---------+
1   | 2011-01-01 12:00:00|   1   |    0    |    0    |
1   | 2011-01-01 12:30:00|   1   |    0    |    0    |
1   | 2011-01-01 15:00:00|   1   |    1    |    2    |
1   | 2011-01-01 16:00:00|   1   |    2    |    3    |
1   | 2011-01-01 16:00:00|   2   |    0    |    0    |
1   | 2011-01-01 16:20:00|   2   |    0    |    0    |
2   | 2011-02-02 11:00:00|   1   |    0    |    0    |
2   | 2011-02-02 13:00:00|   1   |    1    |    1    |
1   | 2011-02-02 16:20:00|   1   |    2    |    4    |
1   | 2011-02-02 16:30:00|   2   |    1    |    2    |

Postgresql8.2.15に基づくGreenplum4.21を使用しています

前もって感謝します!ギリビ

4

2 に答える 2

2

少なくとも簡単に、ウィンドウ関数でこれを行う方法がわかりません。

私が知っている最も簡単な方法は、select句で相関サブクエリを使用することです。

select t.*,
       (select count(*) from t t2
        where t2.user_id = t.user_id and t2.item = t.item and
              t2.req_time < t.req_time - interval '1 hour'
       ) as value1,
       (select SUM(is_active) from t t2
        where t2.user_id = t.user_id and t2.item = t.item and
              t2.req_time < t.req_time - interval '1 hour'
       ) as value2
from t

これは、相関サブクエリなしで実行できます。もう少し面倒です。. .

select t.user_id, t.req_time, t.item,
       count(*) as value1,
       sum(t2.isactive) as value2
from t left outer join
     t t2
     on t.user_id = t2.user_id and
        t.item = t2.item and
        t2.req_time < t.req_time - interval '1 hour'
group by t.user_id, t.req_time, t.item 

これは、相関サブクエリ バージョンよりもさらに効率的である可能性があります (2 つの相関があるため)。そして、それは GreenPlum で動作するはずです。相関サブクエリがサポートされていないことに気づきませんでした。これは、ANSI からの大幅な逸脱です。

于 2013-02-21T16:57:07.813 に答える
1

8.3 で SQL Fiddle。副選択は 1 つだけです。

select user_id, req_time, item, v[1] as value1, v[2] as value2
from (
    select t.*,
        (
            select array[
                coalesce(sum(is_active::integer), 0),
                count(*)
                ] as v
            from t s
            where
                user_id = t.user_id
                and item = t.item
                and req_time <= t.req_time - interval '1 hour'
        ) as v
    from t
) s
order by req_time, user_id, item
于 2013-02-21T18:11:14.533 に答える