2017-02-01 15 views
1

からMAX値を選択するために、窓関数を使用して、私は次のように私はテーブルを持っている場合たとえば、過去2年以内にPostgresqlの:日付範囲

から最大値を選択しようとしています:

|person_id | pass_or_fail | timestamp| 
|----------|--------------|-----------| 
|1234  | 1   | 1990-01-01| 
|1234  | 0   | 1995-01-01| 
|1234  | NULL   | 1995-12-12| 
|6789  | 0   | 1990-01-01| 
|6789  | 0   | 1991-01-01| 
|6789  | 1   | 1995-01-01| 
|6789  | 1   | 1996-01-01| 
|6789  | 0   | 1997-01-01| 
|6789  | NULL   | 1997-03-03| 

私は私のクエリから次を取得したい:

person_id |highest_grade_from_past_two_years | pass_or_fail | timestamp 
1234  |1         | 1   | 1990-01-01 
1234  |0         | 0   | 1995-01-01 
1234  |0         | NULL   | 1995-12-12 
6789  |0         | 0   | 1990-01-01 
6789  |0         | 0   | 1991-01-01 
6789  |1         | 1   | 1995-01-01 
6789  |1         | 1   | 1996-01-01 
6789  |1         | 0   | 1997-01-01 
6789  |1         | NULL   | 1997-03-03 

私は私にこの結果を与えるために私の窓関数を書くことができますどのように?

答えて

0

このクエリをウィンドウ関数で記述する方法はありません。窓なしのバージョン:

SELECT t1.person_id, 
     max(t2.pass_or_fail) AS highest_grade_from_past_two_years, 
     t1.pass_or_fail, 
     t1.timestamp 
FROM t AS t1 
    JOIN t AS t2 ON (
      t1.person_id = t2.person_id 
      AND t2.timestamp < t1.timestamp + '2 year'::interval 
      AND t2.timestamp <= t1.timestamp 
    ) 
GROUP BY 1, 3, 4 
+0

上記の2番目の表は、私のクエリ結果を見た目にしたいものです。私は1つのテーブルでのみ作業しています –

+0

両方のテーブルが同じですが、selectステートメントでサブクエリを使用しないようにしています - セパレートで各行に対して実行します –

0

実際の年に参加して - 1(存在する場合)

select p1.person_id, p1.pass_or_fail, p1.timestamp, 
     case when coalesce(p1.pass_or_fail,0) > coalesce(p2.pass_or_fail,0) 
      then coalesce(p1.pass_or_fail,0) else coalesce(p2.pass_or_fail,0) end as highest_grade_from_past_two_years 
from person p1 
    left join person p2 
    on p1.person_id = p2.person_id 
     and extract(year from p2.timestamp) = extract(year from p1.timestamp) - 1 
order by p1.person_id, p1.timestamp 

。ここ

チェック:http://rextester.com/BNPW52530

0

私は、ウィンドウ関数を使用する明白な方法が表示されません。相関サブクエリまたは参加横方向に働くだろう:

select t.*, 
     (select max(t2.pass_or_fail) 
     from t t2 
     where t2.person_id = t.person_id and 
       t2.timestamp <= t.timestamp and 
       t2.timestamp >= t.timestamp - interval '2 year' 
     ) as highest_grade_from_past_two_years 
from t; 

私はあなたが窓関数で取得することができ、最も近いが、範囲指定だと思います。しかし、Postgresはrangepreceding仕様をサポートしていません。

+0

selectでサブクエリを置くのはあまり良いことではありません - 。 –

+0

@RomanTkachuk。 。 。私はあなたがSQLだけでなく私も理解しているとは思わない。相関サブクエリはここで問題ありません。これは 't(person_id、timestamp、pass_or_fail)'のインデックスでより速く実行されます。 –