2016-10-04 4 views
2

У меня есть две таблицы differents. У них есть несколько общих столбцов, в этом примере можно сказать «имя» и «идентификатор».Выделить все из одной таблицы, где некоторые столбцы соответствуют другому выбору

Делая

( SELECT name,id FROM table1 
    EXCEPT 
    SELECT name,id FROM table2) 
UNION ALL 
( SELECT name,id FROM table2 
    EXCEPT 
    SELECT name,id FROM table1) 

получить список элементов, которые находятся на одной таблетке, но не в другой.

До этого момента все в порядке.

Но теперь я хочу сделать выбор из table1, где имя и идентификатор совпадают с результатом запроса выше.

+0

Что вы имеете в виду выбрать из table1, где результат соответствует выше запрос? Разве это не запрос перед UNION ALL? – kbball

+0

Да, но мне нужны все столбцы. – TiraULTI

+0

Хорошо - обновил мой ответ ниже. Дайте мне знать, что вы думаете – kbball

ответ

2

После много комментариев, которые я думаю, это то, что вы после ...

SELECT T1.* 
FROM table1 t1 
LEFT JOIN table2 t2 
    on T1.ID = T2.ID 
    and T1.Name = T2.Name 
    AND E2.event_Time_UTC between convert(datetime,'2016-02-09 00:00:20',101) and convert(datetime '2016-02-09 23:59:52',101) 
WHERE T2.Name is null 
AND E1.Event_Time_UTC between convert(datetime,'2016-02-09 00:00:20',101) and convert(datetime,'2016-02-09 23:59:52',101) 

вы можете позволить неявное приведение работать, но выше явный подход ...

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

Левое соединение позволяет нам возвращать все записи из 1-го стола и только те, которые соответствуют 2-му.

t1. * Возвращает только столбцы из таблицы1. Критерий join (on) позволяет нам идентифицировать те записи, которые соответствуют, поэтому они могут быть исключены в where cluase на 'where t2.name is null', они всегда будут равны null, если в t2 нет записи.

Таким образом, вы получаете набор результатов: все записи из t1 без соответствующей записи по имени и идентификатору в таблице2. не

enter image description here

---------- СОДЕРЖАНИЕ НИЖЕ БОЛЬШЕ НЕ СООТВЕТСТВУЮЩИЕ НА ОСНОВЕ КОММЕНТАРИЕВ ------

Я отредактированное предыдущий ответ МНОГО, потому что с помощью SQL Server не MYSQL и я знаете, что вам нужны несколько записей, а не таблица1 и таблица2.

Ниже я создаю две таблицы: table1 и table2. Затем я заполняю таблицы1 и таблицу2 некоторыми примерами данных

Затем я показываю, как получить только те записи, которые существуют в одной таблице, но не другие; возвращая отдельную ROW для каждого. Затем я подробно расскажу, почему я выбираю этот подход и другие. Я, наконец, рассмотреть то, что вы пытались и пытаются объяснить, почему я не думаю, что он будет работать ...

create table table1 (
    ID int, 
    name varchar(20), 
    col1 varchar(20), 
    col2 varchar(20), 
    col3 varchar(20)); 

Create table table2 (
    id int, 
    name varchar(20)); 

Insert into table1 values (1,'John','col1','col2','col3'); 
Insert into table1 values (2,'Paul','col1','col2','col3'); 
Insert into table1 values (3,'George','col1','col2','col3'); 

Insert into table2 values (1,'John'); 
Insert into table2 values (4,'Ringo'); 

Вариант 1

SELECT T1.name, T1.ID, T1.Col1, T1.Col2, T1.Col3 
FROM Table1 T1 
LEFT JOIN Table2 T2 
on T1.Name = T2.Name 
and T1.ID = T2.ID 
WHERE T2.ID is null 

UNION ALL 

SELECT T2.name, T2.ID, NULL, NULL, NULL 
FROM Table1 T1 
RIGHT JOIN Table2 T2 
on T1.Name = T2.Name 
and T1.ID = T2.ID 
WHERE T1.ID is null ; 

, что приводит к ...

enter image description here

Уведомление John не существует, как в обеих таблицах. У нас есть еще 2 записи из таблицы1 и идентификатор, имя из таблицы2, за которой вы следуете.

Обычно я делал это как полное внешнее соединение, но поскольку я думаю, что вы хотите повторно использовать поля имени и id для связи с BOTH-таблицами в том же столбце, мы должны были использовать этот подход и указать все имена столбцов в таблицу 1 и поместите NULL для каждого столбца в таблице 1 при отображении записей из таблицы2, чтобы сделать вывод второго соединения запроса первым. Мы просто не можем использовать *

Вариант 2: Использование полное внешнее объединение ... со всеми столбцами из T1

SELECT T1.* 
FROM Table1 T1 
FULL OUTER JOIN Table2 T2 
on T1.ID = T2.ID 
and T1.Name = T2.Name 
WHERE (T1.ID is null or T2.ID is null) 

вы получите это ..., который не показывает Ринго ...

enter image description here

Но тогда я хотел бы спросить, почему вам нужно что-нибудь из таблицы 2 .... на всех, так что я думаю, что вы все еще желая показать ID, имя из table2, когда он не существует в table1 ,

Вот почему я думаю, что вы после того, как это вытекает из 1-го запроса, используя объединение всех ..

Вариант 3 Я полагаю, мы могли бы избежать второго запроса в варианте 1, делая .. .

SELECT coalesce(T1.Name, T2.name) as name, coalesce(T1.Id,T2.ID) as ID, T1.col1, T1.Col2, T1.Col3 
FROM Table1 T1 
FULL OUTER JOIN Table2 T2 
on T1.ID = T2.ID 
and T1.Name = T2.Name 
WHERE (T1.ID is null or T2.ID is null) 

, который дает нам ... как то, что я считаю желаемые результаты.

Это работает, потому что мы знаем, что нам нужно только имя, id из таблицы2, и все значения столбца в таблице1 будут пустыми.

Обратите внимание, что во всех случаях мы просто не можем использовать Tablename. *, Чтобы выбрать все записи из таблицы1.

enter image description here

Это то, что вы пробовали:

( SELECT name,id FROM table1 
    EXCEPT 
    SELECT name,id FROM table2) 
UNION ALL 
( SELECT name,id FROM table2 
    EXCEPT 
    SELECT name,id FROM table1) 
  1. Предполагая, что вы хотите использовать идентификатор, поля Имя; вы не можете выбрать *. Зачем? потому что записи в таблице 2, не указанные в таблице 1, не указаны в таблице 1. В моем примере, если вы хотите, чтобы Ринго появлялся, вам нужно ссылаться на таблицу2! Кроме того, * не дает вам возможности «Объединить» идентификатор и поля имени вместе, как я сделал в варианте 3 выше.
  2. Если вы хотите только колонки из таблицы1, это означает, что вы НИКОГДА не увидите данные из таблицы2 ... Если вам не нужны данные из таблицы2 (например, ringo в моем примере), то зачем нам это делать? союз вообще?) Я предполагаю, что вы хотите ринго, таким образом, вы ИМЕЕТЕ где-то ссылочное имя, id из таблицы2.
+0

Их структуры arent идентичны. Это проблема, у них есть некоторые общие столбцы, но у них есть другие, которые разные. Я хочу ВСЕ столбцы из таблицы с данными. – TiraULTI

+0

Затем перечислите столбцы индивидуализированно и поместите «NULL» во второй выбор для тех столбцов, которые не существуют. вам может потребоваться псевдоним столбцов из таблицы2, которые соответствуют таблице1, поэтому вы можете легко ссылаться на них, но если количество столбцов не так уж плохо, это будет довольно легко сделать. Или, если количество столбцов велико, просто выберите столбцы из системной таблицы и скопируйте/вставьте их в select ... – xQbert

+0

Возможно, вы захотите прочитать о типах соединений в [ужасе кодирования] (https: //blog.codinghorror .com/a-visual-explain-of-sql-joins /) полное внешнее соединение дает вам все записи из обеих таблиц, соответствующих или нет, и, проверяя значение null по критериям соединения, вы можете показать, где они не пересекаются. – xQbert

1

Вы также можете сделать это с NOT EXISTS:

SELECT * 
FROM table1 
WHERE 
NOT EXISTS 
(SELECT 1 
FROM table2 
WHERE table1.id = table2.id 
AND table1.name = table2.name) 
+0

Хорошо, я попробую это. Спасибо – TiraULTI

+0

Просто обновите первую строку до * – kbball

+0

По какой-то причине этот запрос не дает мне никакой строки вообще. – TiraULTI

0
;with cte as 
(
    ( SELECT name,id FROM table1 
     EXCEPT 
     SELECT name,id FROM table2) 
     UNION ALL 
    ( SELECT name,id FROM table2 
     EXCEPT 
     SELECT name,id FROM table1) 
) 
Select * 
from table1 as tbl1 
where 
    tbl1.id = cte.id 
    and tbl1.name = cte.name 
+0

Обертка точно такого же запроса в CTE не имеет никакого значения. Возможно, вам стоит попытаться объяснить, что вы пытаетесь достичь, и как этот ответ помогает. –

+0

Не могли бы вы объяснить, что такое cte? – TiraULTI

+0

CTE - это общее выражение таблицы. Высокий уровень, это способ запроса результатов, возвращаемых из запроса внутри cte. Быстрый поиск в Google даст вам много информации об этом. – luke