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

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

我有 table 喜欢那里:

 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 是其他 table.

的外键

现在我需要查询与某些标签('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 应该可以在 MySQL (Keep all records in "WHERE IN()" clause, even if they are not found):

  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。

创建临时 table 根本不起作用(我从中得到 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 保持空关系吗?如果在 table?

中没有相应的行,甚至还有任何其他想法可以让标签 'eee' 的数量为 NULL

每个请求的标签列表可能不同。

本案在线:http://rextester.com/CRQY46630

------ 编辑 ----- 我用过滤器 where 扩展了这个问题,因为 a_horse_with_no_name 的回答很好,但没有涵盖我的整个案例(我认为这个 where 不管那里)

您的外连接方法确实有效。您只需要从 "outer" 加入的 table 中获取标签值,而不是从 "table":

中获取标签值
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


在问题范围扩大后编辑

如果要在基础 table 上进行过滤,则需要将

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