ユーザーのために2種類のイベントを関連付けようとしています。 「A」イベントの前のそのユーザーの最新のイベント「A」とともに、すべてのイベント「B」を表示したい。どうすればこれを達成できますか?特に、Postgresでこれを実行しようとしています。
ウィンドウ関数で「where」句を使用できることを望んでいました。この場合、「where event = 'A'」でLAG()を実行できますが、それは不可能のようです。
何かお勧めですか?
データ例:
|user |time|event|
|-----|----|-----|
|Alice|1 |A |
|Bob |2 |A |
|Alice|3 |A |
|Alice|4 |B |
|Bob |5 |B |
|Alice|6 |B |
望ましい結果:
|user |event_b_time|last_event_a_time|
|-----|------------|-----------------|
|Alice|4 |3 |
|Bob |5 |2 |
|Alice|6 |3 |
PostgreSQL 9.5.4を使用してGordonのアプローチを試したところ、
FILTERは非集約ウィンドウ関数には実装されていません
つまり、FILTER
でlag()
を使用することはできません。そこで、別のウィンドウフレームであるmax()
とCTEを使用してGordonのクエリを変更しました。
WITH subq AS (
SELECT
"user", event, time as event_b_time,
max(time) FILTER (WHERE event = 'A') OVER (
PARTITION BY "user"
ORDER BY time
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
) AS last_event_a_time
FROM events
ORDER BY time
)
SELECT
"user", event_b_time, last_event_a_time
FROM subq
WHERE event = 'B';
これがPostgreSQL 9.5.4で動作することを確認しました。
FILTER
トリックを提供してくれたGordonに感謝します。
これが1つの方法です。
select t.*
from (select t.*,
lag(time) filter (where event = 'A') (partition by user order by time)
from t
) t
where event = 'B';
相関サブクエリ/ラテラル結合の方がパフォーマンスが優れている可能性があります。
ここではウィンドウ関数は必要ありません。すべてのB
イベントを検索し、それらのそれぞれについて、サブクエリを介して同じユーザーの最新のA
を検索します。そのような何かがそれをするはずです:
SELECT
"user",
time AS event_b_time,
(SELECT time AS last_event_a_time
FROM t t1
WHERE "user"=t.user AND event='A' AND time<t.time
ORDER BY time DESC LIMIT 1)
FROM t
WHERE event='B';
テーブルはt
と呼ばれていると思います(2回使用しました)。