Postgresql

FROM 子句中的條件選擇

  • October 15, 2019

我有兩張桌子:

  • parent帶有列identifier(pkey) 和period;
  • child帶有列identifier(pkey)parent_identifierperiod.

還有其他列,但我沒有在此處列出它們,因為它們並不真正相關。

我想選擇如下時期:

  • 如果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);

引用自:https://dba.stackexchange.com/questions/250875