简体   繁体   English

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

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

I have table like there: 我有像这样的桌子:

 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 is a foreign key to other table. fkey是其他表的外键。

Now I need to query for all amounts asociated with some labels ('bbb', 'eee', 'fff') and with specifed fkey, but i need to keep all unexisting labels with NULL . 现在,我需要查询与某些标签('bbb','eee','fff')和指定的fkey相关联的所有金额,但我需要将所有不存在的标签保留为NULL

For simple query with WHERE IN ('bbb', 'eee', 'fff') I got, of course, only two rows: 对于使用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     |

but excepted result should be: 但排除结果应为:

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

I tried also SELECT label UNION ALL label (...) LEFT JOIN which should work on MySQL ( Keep all records in "WHERE IN()" clause, even if they are not found ): 我还尝试了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;

and also with WITH statement: 以及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;

but always this LEFT JOIN give me 2 rows istead 3. 但总是这个LEFT JOIN给我2行而不是3行。

Create temporary table doesn't work at all (I got 0 rows from it and I cannot use this in join): 创建临时表根本不起作用(我从中得到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

Any idea how to enforce Postgres to keep empty relation? 任何想法如何强制Postgres保持空关系? Or even any other idea to get label 'eee' with NULL amount if there is not row for this in table? 甚至在表中没有行的情况下,甚至还有其他任何想法来获得带有空值的标签“ eee”?

List of labels can be different on every request. 每个请求的标签列表可以不同。

This case online: http://rextester.com/CRQY46630 在线该案例: http : //rextester.com/CRQY46630

------ EDIT ----- I extended this question with filter where , because answer from a_horse_with_no_name is great, but not cover my whole case (I supposed this where no matter there) ------编辑-----我用filter where扩展了这个问题,因为来自a_horse_with_no_name的答案很好,但没有涵盖我的全部情况(我认为无论在where都可以)

Your approach with the outer join does work. 您使用外部联接的方法确实有效。 You just need to take the label value from the "outer" joined table, not from the "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;

Online example: http://rextester.com/LESK82163 在线示例: http : //rextester.com/LESK82163


Edit after the scope of the question was extended. 扩大问题范围后进行编辑

If you want to filter on the base table, you need to move the into the JOIN condition, not the where clause: 如果要在基表上进行过滤,则需要将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; --<< 

Online example: http://rextester.com/XDO76971 在线示例: http : //rextester.com/XDO76971

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM