在 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; --<<
我有 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; --<<