Postgresql
FROM 子句中的條件選擇
我有兩張桌子:
parent
帶有列identifier
(pkey) 和period
;child
帶有列identifier
(pkey)parent_identifier
和period
.還有其他列,但我沒有在此處列出它們,因為它們並不真正相關。
我想選擇如下時期:
- 如果
parent
匹配某個謂詞,則選擇parent.period
.child.period
如果沒有,則從每個孩子中挑選。我有以下查詢:
select q.period from parent, lateral ( select parent.period where <some complex predicate> union all select child.period from child where child.parent_identifier = parent.identifier and not(<the same complex predicate as above>) ) as q(period);
雖然此查詢有效並返回預期的時間段,但我想知道是否可以以
<some complex predicate>
不必評估兩次的方式重寫此查詢,以提高性能(儘管是一個小因素)和通用查詢結構以表示if ... else ...
上述. 理想情況下,我想遍歷每個parent
/child
行並只評估一次謂詞。我試圖引入一個
case when <some complex predicate> then ... else ... end
子句,但我沒有把它弄對。我不確定這在FROM
條款中是否可能。這可能嗎?我也
select case when <predicate> then parent.period else unnest(array(select child.period from child where ...)) from parent
想到了(雖然我沒有嘗試過,所以它也可能被禁止使用case when ...
),但我不確定首先創建然後取消嵌套數組是否真的是最優的。另外,我不太喜歡選擇中的集合返回函式,例如unnest
。
以下查詢對每一
parent
行只評估一次昂貴的謂詞。為此,謂詞在單獨的子查詢中進行評估。第一個版本使用橫向連接,第二個版本使用內部連接。這符合問題的要求。select q2.period from parent, lateral ( select <some complex predicate> ) as q1(predicate), lateral ( select parent.period where q1.predicate union all select child.period from child where child.parent_identifier = parent.identifier and not(q1.predicate) ) as q2(period);
select q2.period from parent, inner join ( select parent.identifier, <some complex predicate> from parent ) as q1(identifier, predicate) on parent.identifier = q1.identifier, lateral ( select parent.period where q1.predicate union all select child.period from child where child.parent_identifier = parent.identifier and not(q1.predicate) ) as q2(period);