我有两张桌子:
表A:
id name
------------
1 Scott
2 Dan
3 Sam
表B:
id name
------------
1 Dan
2 Andi
3 Jess
我的结果必须是:
Id Name Found
1 Scott A
2 Dan C i.e. found in both
3 Sam A
2 Andi B
3 Jess B
我可以使用UNION获取结果,但如何创建Found
列?
答案 0 :(得分:4)
使用:
SELECT CASE
WHEN y.name IS NULL THEN z.id
WHEN z.name IS NULL THEN y.id
ELSE y.id
END AS id,
x.name,
CASE
WHEN y.name IS NULL THEN 'B'
WHEN z.name IS NULL THEN 'A'
ELSE 'C'
END AS found
FROM (SELECT a.name
FROM TABLE_A a
UNION
SELECT b.name
FROM TABLE_B b) x
LEFT JOIN TABLE_A y ON y.name = x.name
LEFT JOIN TABLE_B z ON z.name = x.name
替代:
SELECT COALESCE(y.id, z.id) AS id,
x.name,
CASE
WHEN y.name IS NULL THEN 'B'
WHEN z.name IS NULL THEN 'A'
ELSE 'C'
END AS found
FROM (SELECT a.name
FROM TABLE_A a
UNION
SELECT b.name
FROM TABLE_B b) x
LEFT JOIN TABLE_A y ON y.name = x.name
LEFT JOIN TABLE_B z ON z.name = x.name
答案 1 :(得分:1)
执行此操作的方法是使用FULL OUTER JOIN,但由于MySQL不支持,因此您可以使用LEFT JOIN和INNER JOIN以及RIGHT JOIN的组合。
(
SELECT A.Id, A.Name, 'A' AS Found
FROM A LEFT JOIN B ON A.Name = B.Name
WHERE B.Name IS NULL
)
UNION ALL
(
SELECT B.Id, B.Name, 'B' AS Found
FROM A RIGHT JOIN B ON A.Name = B.Name
WHERE A.Name IS NULL
)
UNION ALL
(
SELECT A.Id, A.Name, 'C' AS Found
FROM A JOIN B ON A.Name = B.Name
)
实际上,您只需要LEFT和RIGHT JOIN,因为您可以在执行其他两个连接之一的同时处理INNER JOIN。我认为上面的原理更清楚地说明了原理,但在实践中,以下内容会提供更好的表现:
SELECT A.Id, A.Name, IF(B.Name IS NULL, 'A', 'C') AS Found
FROM A LEFT JOIN B ON A.Name = B.Name
UNION ALL
SELECT B.Id, B.Name, 'B' AS Found
FROM A RIGHT JOIN B ON A.Name = B.Name
WHERE A.Name IS NULL
结果:
Id Name Found 1 Scott A 2 Dan C 3 Sam A 2 Andi B 3 Jess B
答案 2 :(得分:0)
在我看来,你有效地希望同时进行左右连接。这在技术上是不可能的,因为您总是需要一个参考表。我能想到的唯一方法是:
SELECT tableA.*
LEFT JOIN tableB.* USING name
UNION DISTINCT SELECT tableB.*
LEFT JOIN tableA USING name
在考虑了一些之后,你也可以做到:
SELECT tableA.*
LEFT JOIN tableB.* USING name
RIGHT JOIN tableB.* USING name
......虽然我不确定这是否有效。
答案 3 :(得分:0)
select tmp.name, case count(*) when 1 then tmp.tbl else 'C' end found
from (select id, name, 'A' tbl from TableA
union all
select id, name, 'B' tbl from TableB) as tmp
group by tmp.name;
+-------+-------+
| name | found |
+-------+-------+
| Andi | B |
| Dan | C |
| Jess | B |
| Sam | A |
| Scott | A |
+-------+-------+
答案 4 :(得分:-1)
错误的答案 你正在寻找“联盟不同”而不仅仅是联盟。 纠正我什么时候被击倒并意识到我错误地阅读了这个问题。
使用简单的电源表示法生成如下的位掩码,使其更清晰,我只需为位掩码插入2的强制转换功能。
with data as (
SELECT Id,Name, 2^0 as bitmask FROM A
UNION ALL
SELECT Id,Name, 2^1 as bitmask FROM B
UNION ALL
SELECT Id,Name, 2^2 as bitmask FROM C)
SELECT Id,Name, SUM(bitmask)
FROM data
GROUP BY Id,Name