簡體   English   中英

在WHERE IN()或SELECT和LEFT JOIN上保持空關系

[英]Keep null relations on WHERE IN() or with SELECT and LEFT JOIN

我有像這樣的桌子:

 table:
 | id | fkey | label | amount |
 |----|------|-------|--------|
 | 1  | 1    | aaa   | 10     |
 | 2  | 1    | bbb   | 15     |
 | 3  | 1    | fff   | 99     |
 | 4  | 1    | jjj   | 33     |
 | 5  | 2    | fff   | 10     |

fkey是其他表的外鍵。

現在,我需要查詢與某些標簽('bbb','eee','fff')和指定的fkey相關聯的所有金額,但我需要將所有不存在的標簽保留為NULL

對於使用WHERE IN ('bbb', 'eee', 'fff')簡單查詢,我當然只有兩行:

 SELECT label, amount FROM table WHERE label IN ('bbb', 'eee', 'fff') AND fkey = 1;

 | label | amount |
 |-------|--------|
 | bbb   | 15     |
 | fff   | 99     |

但排除結果應為:

 | label | amount |
 |-------|--------|
 | bbb   | 15     |
 | eee   | NULL   |
 | fff   | 99     |

我還嘗試了SELECT label UNION ALL label (...) LEFT JOIN ,該SELECT label UNION ALL label (...) LEFT JOIN應在MySQL上運行( 即使未找到所有記錄,也請保留在“ WHERE IN()”子句中 ):

  SELECT T.label, T.amount FROM (
    SELECT 'bbb' AS "lbl"
    UNION ALL 'eee' AS "lbl"
    UNION ALL 'fff' AS "lbl"
  ) LABELS
  LEFT OUTER JOIN table T ON (LABELS."lbl" = T."label")
  WHERE T.fkey = 1;

以及WITH語句:

  WITH LABELS AS (
    SELECT 'bbb' AS "lbl"
    UNION ALL 'eee' AS "lbl"
    UNION ALL 'fff' AS "lbl"
  )
  SELECT T.label, T.amount FROM LABELS
  LEFT OUTER JOIN table T ON (LABELS."lbl" = T."label")
  WHERE T.fkey = 1;

但總是這個LEFT JOIN給我2行而不是3行。

創建臨時表根本不起作用(我從中得到0行,因此無法在連接中使用它):

 CREATE TEMPORARY TABLE __ids (
   id VARCHAR(9) PRIMARY KEY
 ) ON COMMIT DELETE ROWS;

 INSERT INTO __ids (id) VALUES
   ('bbb'),
   ('eee'),
   ('fff');

 SELECT
   *
 FROM __ids

任何想法如何強制Postgres保持空關系? 甚至在表中沒有行的情況下,甚至還有其他任何想法來獲得帶有空值的標簽“ eee”?

每個請求的標簽列表可以不同。

在線該案例: http : //rextester.com/CRQY46630

------編輯-----我用filter where擴展了這個問題,因為來自a_horse_with_no_name的答案很好,但沒有涵蓋我的全部情況(我認為無論在where都可以)

您使用外部聯接的方法確實有效。 您只需要從“外部”聯接表中獲取標簽值,而不是從“表”中獲取:

with labels (lbl) as (
  values ('bbb'), ('eee'), ('fff')
)
select l.lbl,  --<< this is different to your query
       t.amount 
from labels l 
  left outer join "table" t on l.lbl = t.label;

在線示例: http : //rextester.com/LESK82163


擴大問題范圍后進行編輯

如果要在基表上進行過濾,則需要將JOIN條件移動到JOIN條件,而不是where子句:

with labels (lbl) as (
  values ('bbb'), ('eee'), ('fff')
)
select l.lbl,  --<< this is different to your query
       t.amount 
from labels l 
  left outer join "table" t 
               on l.lbl = t.label
              and t.fkey = 1; --<< 

在線示例: http : //rextester.com/XDO76971

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM