繁体   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