У меня две таблицы:

T1 
A  
B  
C  
D

T2  
A  
B  
E  
F  
G  

Теперь я хочу получить запрос, который объединит эти две таблицы, но исключает одни и те же записи. Таблица вывода должна быть такой:

T1T2 
C  
D  
E  
F  
G

Как это сделать?

0
Josef 5 Янв 2016 в 14:29

4 ответа

Лучший ответ

Похоже, вам нужно FULL OUTER JOIN и исключить общую часть. Вы можете смоделировать это с помощью:

SELECT T1.col_name
FROM T1 
LEFT JOIN T2
  ON T1.col_name = T2.col_name
WHERE T2.col_name IS NULL
UNION
SELECT T2.col_name
FROM T2 
LEFT JOIN T1
  ON T1.col_name = T2.col_name
WHERE T1.col_name IS NULL;

SqlFiddleDemo < / kbd>

╔══════════╗
║ col_name ║
╠══════════╣
║ C        ║
║ D        ║
║ E        ║
║ F        ║
║ G        ║
╚══════════╝

Дополнительная информация: Визуальное представление объединений SQL

enter image description here

SELECT <select_list>
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.Key = B.Key
WHERE A.Key IS NULL OR B.Key IS NULL

К сожалению, MySQL не поддерживает FULL OUTER JOIN, поэтому я использовал объединение 2 LEFT JOIN.

enter image description here

enter image description here

Все изображения из http://www.codeproject.com/Articles / 33052 / Визуальное представление-SQL-объединений

Дополнение

Но что, если у меня есть две разные таблицы с разными столбцами, но в обеих есть один и тот же столбец? Используемые операторы SELECT имеют другое количество столбцов

Вы можете легко расширить его дополнительными столбцами.

SELECT 'T1' AS tab_name, T1.col_name, T1.col1, NULL AS col2
FROM  T1
LEFT JOIN  T2
  ON T1.col_name=  T2.col_name
WHERE T2.col_name IS NULL
UNION
SELECT 'T2' AS tab_name, T2.col_name, NULL, T2.col2
FROM  T2
LEFT JOIN  T1
  ON T1.col_name=  T2.col_name
WHERE T1.col_name IS NULL;

LiveDemo

Выход:

╔══════════╦══════════╦══════╦═════════════════════╗
║ tab_name ║ col_name ║ col1 ║        col2         ║
╠══════════╬══════════╬══════╬═════════════════════╣
║ T1       ║ C        ║    3 ║                     ║
║ T1       ║ D        ║    4 ║                     ║
║ T2       ║ E        ║      ║ 2016-01-03 00:00:00 ║
║ T2       ║ F        ║      ║ 2016-01-02 00:00:00 ║
║ T2       ║ G        ║      ║ 2016-01-01 00:00:00 ║
╚══════════╩══════════╩══════╩═════════════════════╝
5
Community 20 Июн 2020 в 09:12

Попробуйте пересечь две таблицы. вы можете увидеть различия.

SELECT T1.col_name
FROM (
SELECT T1.col_name FROM T1
UNION ALL
SELECT T2.col_name FROM T2
) T1
GROUP BY col_name
HAVING count(*) = 1
ORDER BY col_name;
0
Venkat.R 5 Янв 2016 в 11:51

Предполагая, что у вас нет дубликатов ни в одной из таблиц, в одном из подходов используется union all и агрегирование:

select col1, col2, . . .
from (select t1.* from table1 t1
      union all
      select t2.* from table2 t2
     ) tt
group by col1, col2, . . .
having count(*) = 1;

Фактически, вы можете смягчить условие, чтобы не было дубликатов, но тогда вам нужно указать, что с ними делать.

0
Gordon Linoff 5 Янв 2016 в 11:41

Я вижу два возможных решения.

Использование UNION ALL вместе с внешним выбором с GROUP BY x HAVING COUNT(x) = 1:

SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT a FROM t2) as t12 GROUP BY a HAVING COUNT(a) = 1

Использование UNION для объединения двух SELECT, отфильтрованных по подзапросам:

(SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2)) UNION (SELECT a FROM t2 WHERE a NOT IN (SELECT a FROM t1))

Не уверен, какой из них наиболее эффективен!

Посмотрите его в действии здесь.

1
deadbeef 5 Янв 2016 в 12:04