2017-05-25 50 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()函數兩次,如果可能的話,我不希望創建臨時表。

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' - 這很醜陋。爲什麼不'創建

+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返回結果,則在聯合產生結果後,聯合將不會產生任何結果else查詢。

+0

謝謝!當你做'不存在的地方時,限制1'是做什麼的(select * from filtered_records limit 1)'? –

+2

在不存在的情況下(子查詢限制1),此處使用限制來減少執行時間。因爲我們只需要檢查過濾記錄中是否有記錄。 –