2017-05-25 4 views
0

私はPostgreSQL関数find_all_records_with_params()を持っていて、SETOF recordsを返します。レコードのテーブルには、次の列があります。PostgreSQL:条件付きの行をすべて選択し、条件を無視して最も古い行を選択します。

table records(
id integer, 
type integer, 
created date, 
content text 
); 

私はcurrent_date - createdが90日超であるすべてのレコードを選択したいと思います。ただし、このクエリが存在しない場合は、最初にcreatedという日付のレコードを1つ選択します。

私はこれを再帰的なcte(以下に示します)を使用して実行しようとしましたが、if/elseロジックは使用できません。可能であれば、find_all_records_with_params()関数を2回呼び出すことを避けようとしており、私は一時テーブルを作成したくありません。

with most_records as (select * from find_all_records_with_params()), 
filtered_records as (select * from most_records where current_date - created > 90) 
if exists(select * from filtered_records) then 
select * from filtered_records; 
else 
select * from most_records order by created asc limit 1; 
end if; 
+0

'current_date - created> 90' - それはかなり醜いです。どうして 'created

+0

@DavidAldridgeは 'current_date - created'より' current_date - 90'を実行するとパフォーマンス上の利点がありますか?その値をキャッシュしていますか? –

+0

これはオプティマイザがインデックスを使うことを可能にしますが、読むのがはるかに簡単です - 私は25年間SQLを書いてきましたが、 'current_date - created> 90'を私の目の前に置きました。それが何を意味するか。 –

答えて

3
with most_records as (select * from find_all_records_with_params()), 
filtered_records as (select * from most_records where current_date - created > 90) 
select * from filtered_records 
union 
select * from 
(select * from most_records 
where not exists (select * from filtered_records limit 1) 
order by created asc limit 1) a ; 

私はあなたに必要な結果を達成するために、ユニオンクエリを使用していました。 filtered_recordsが結果を返す場合、unionの後のqueryは、unionがresultを生成した後にelseの結果を生成しません。

+0

ありがとう! 'limit 1'は'どこにもない(select * from filtered_records limit 1) 'をしたときに何をしますか? –

+2

whereは存在しません(サブクエリー制限1)。ここでは、実行時間を短縮するために制限が使用されています。フィルタリングされたレコードにレコードがあるかどうかを確認するだけで済みます。 –

関連する問題