2010-06-08 111 views
2

我有两个表:选择联合查询?

表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

我觉得在结果中的'Id'栏应阅读'4 Andi ... 5 Jess'。 – eykanal 2010-06-08 18:26:28

回答

1

做到这一点的方法是使用一个FULL OUTER JOIN,但由于这是不是在MySQL的支持,您可以改用组合一个左加入和内部加入和右加入。

(
    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 
) 

其实,你只需要左右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  
+0

我选择了第二个查询,因为它比其他查询快得多。谢谢!!! – Kris1511 2010-06-09 15:12:10

-1

错误答案 您正在寻找“union distinct”而不仅仅是union。 更正时,我得到了低调,并意识到我错读了问题。

如下所示生成一个位掩码,使用简单的功率表示法使其更清晰,即时插入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 
+0

这不行;他想知道每个表来自哪个表,不同的只是删除重复项。 – eykanal 2010-06-08 18:30:39

+1

-1:UNION是UNION DISTINCT的同义词。请参阅手册:http://dev.mysql.com/doc/refman/5.0/en/union.html – 2010-06-08 18:49:36

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 

...虽然我不知道这是有效的。

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 
+0

+1 This work well – 2010-06-08 18:40:22

+0

此外,结果中“Id”列的逻辑似乎为“COALESCE (x.id,y.id)'。 – VeeArr 2010-06-08 18:41:24

+0

@VeeArr:你的意思是'COALESCE(y.id,z。id)':) – 2010-06-08 18:43:02

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  | 
+-------+-------+