2017-07-06 11 views
1

データベースは、HPのVertica 7やPostgreSQL 9.最後の1日に使用する支払用カードSQL結合をウィンドウ関数に書き換える方法は?

create table test (
id int, 
card_id int, 
tran_dt date, 
amount int 
); 

insert into test values (1, 1, '2017-07-06', 10); 
insert into test values (2, 1, '2017-06-01', 20); 
insert into test values (3, 1, '2017-05-01', 30); 
insert into test values (4, 1, '2017-04-01', 40); 
insert into test values (5, 2, '2017-07-04', 10); 

、最後の90日間でそのカードに課金上限額が何であるかです。

select t.card_id, max(t2.amount) max 
from test t 
join test t2 on t2.card_id=t.card_id and t2.tran_dt>='2017-04-06' 
where t.tran_dt>='2017-07-06' 
group by t.card_id 
order by t.card_id; 

結果は、私は、SQLウィンドウ関数に問合せをリライトしたい

card_id max 
------- --- 
1   30 

正しいです。

select card_id, max(amount) over(partition by card_id order by tran_dt range between '60 days' preceding and current row) max 
from test 
where card_id in (select card_id from test where tran_dt>='2017-07-06') 
order by card_id; 

結果セットは一致しません。どうすればできますか?ここ

テストデータ: http://sqlfiddle.com/#!17/db317/1

+0

はまず、PostgresのとのVerticaは、2つの非常に異なるものです。第2に、なぜ2つの非常に異なるクエリの結果が同じであると期待していますか? – mustaccio

答えて

1

私の知る限りでは、PostgreSQLの窓関数は、このようにrange between '90 days' precedingが動作しませんrange preceding有界をサポートしていません。 (あなたが必要なものについて

SELECT c.card_id, t.amount, g.d as d_series 
FROM generate_series(
    '2017-04-06'::timestamp, '2017-07-06'::timestamp, '1 day'::interval 
) g(d) 
CROSS JOIN (SELECT distinct card_id from test) c 
LEFT JOIN test t ON t.card_id = c.card_id and t.tran_dt = g.d 
ORDER BY c.card_id, d_series 

:それは支持体は、rows between 90 precedingとしてrows preceding有界んが、その後、あなたは、時間ベースの行を操作するためのウィンドウの機能については、次のような時系列クエリを組み立てる必要があるだろうあなたの質問の記述に基づいて)、私はgroup byを使用することに固執します。

1

私はPostgreSQLを試すことはできませんが、VerticaではANSI標準OLAPウィンドウ関数を適用できます。

しかし、2つのクエリをネストする必要があります。ウィンドウ関数は、結果セットで評価する必要があるすべての行がある場合にのみ、賢明な結果を返します。

ただし、「2017-07-06」の行のみが表示されます。

ですから、外側のクエリでその日のためにフィルタリングする必要があります:

WITH olap_output AS (
    SELECT 
    card_id 
    , tran_dt 
    , MAX(amount) OVER (
     PARTITION BY card_id 
     ORDER BY tran_dt 
     RANGE BETWEEN '90 DAYS' PRECEDING AND CURRENT ROW 
    ) AS the_max 
    FROM test 
) 
SELECT 
    card_id 
, the_max 
FROM olap_output 
WHERE tran_dt='2017-07-06' 
; 

card_id|the_max 
     1|  30 
関連する問題