2010-06-08 113 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  | 
+-------+-------+