2013-10-10 3 views
0

У меня есть запрос, который должен вернуть все записи в T1, которые не связаны с записями в Т2:ГДЕ + НЕ СУЩЕСТВУЕТ + 2 Колонки

SELECT DISTINCT fldID, fldValue FROM T1 
WHERE NOT EXISTS 
(
    SELECT T1.fldID, T1.fldValue 
    FROM T2 
    JOIN T1 ON T2.fldID = T1.fldPtr 
)  

Но она возвращает пустой набор - должен быть один рекорд.

Если я использую запрос, как это (п на одном поле):

SELECT DISTINCT fldID FROM T1 
WHERE fldID NOT IN 
(
    SELECT T1.fldID 
    FROM T2 
    JOIN T1 ON T2.fldID = T1.fldPtr 
)  

Это возвращает правильный результат.

Но SQL Server не поддерживает синтаксис

WHERE (fldID, flrValue) NOT IN .... 

Помогите мне пожалуйста, чтобы выяснить, как составить запрос, который будет проверять несколько столбцов?

Спасибо!

+0

В первом запросе вам не нужно присоединяться к t1 в подзапросе (он даст нулевые строки). Попробуйте: 'WHERE NOT EXISTS ( ВЫБОР 1 оТ T2 ГДЕ T2.fldID = T1.fldPtr ) ' – joop

ответ

5

Вы можете также использовать EXCEPT для этого:

SELECT DISTINCT fldID, fldValue FROM T1 

EXCEPT 

SELECT T1.fldID, T1.fldValue 
FROM T2 
    JOIN T1 ON T2.fldID = T1.fldPtr 
+0

Спасибо! Оно работает! И это решение подходит для моей задачи больше, чем другие. – kaa

1

Используйте обе эти столбцы, если подзапрос присоединиться:

SELECT DISTINCT fldID, fldValue FROM T1 
WHERE NOT EXISTS 
(
    SELECT * 
    FROM T2 
    JOIN T1 ON T2.fldID = T1.fldPtr 
      AND T1.fldValue = T2.flrValue 
) 
+0

Там нет ничего, чтобы сравнить дальше и T1.fldValue = T2.flrValue, таблицы связаны FK на T2.fldID и T1.fldPtr полей – kaa

+1

@YuriyVelichko - Не могли бы вы отредактировать свой вопрос, чтобы предоставить точные столбцы, несколько строк выборочных данных и ожидаемых результатов? Вы получите правильный ответ быстрее. –

0

Нечто подобное (я думаю, что я не уверен, что я 100% понимаю ваш вопрос):

SELECT DISTINCT fldID FROM T1 
WHERE fldID NOT IN 
(
    SELECT T1.fldID 
    FROM T2 
    JOIN T1 ON T2.fldID = T1.fldPtr 
    WHERE T2.flrValue = T1.flrValue 
) 
0

Если вы имеете такую ​​же структуру в обеих таблицах вы можете используйте оператора ИСКЛЮЧЕНИЯ http://technet.microsoft.com/en-us/library/ms188055.aspx

В более общем случае вам необходимо использовать левое соединение и найти нулевые элементы во второй таблице.

2

Более эффективный и элегантный запрос, который будет работать с любой базой данных:

SELECT T1.* 
FROM T1 
LEFT JOIN T2 
    ON T2.fldID = T1.fldPtr 
    AND T2.flrValue = T1.flrValue 
WHERE T2.fldID IS NULL 

ЛЕВАЯ РЕГИСТРИРУЙТЕСЬ попытки соответствовать используя оба критерия, то ИНЕКЕ фильтрует соединения, и только не включается иметь NULL значения для таблицы LEFT JOINed.

Этот подход является ИМХО в значительной степени отраслевым стандартом для поиска несоответствий. Он обычно более эффективен, чем NOT EXIstS(), хотя в любом случае несколько баз данных оптимизируют NOT EXISTS() для этого запроса.

+0

Это зависит от фактических данных и, вероятно, отличается от случая к случаю, но есть несколько статей, показывающих, что 'NOT EXISTS' работает лучше, чем' LEFT JOIN/IS NULL'. [Pinal Dave] (http://blog.sqlauthority.com/2008/04/22/sql-server-better-performance-left-join-or-not-in/) [EXPLAIN EXTENDED] (http: // explainextended .com/2009/09/15/not-in-vs-not-exist-vs-left-join-is-null-sql-server /) –

+0

Спасибо за ответ. Я изучу этот вариант. Но для текущей задачи больше подходит решение от @ w0lf. – kaa

0

попробуйте нижеследующий запрос.

select DISTINCT fldID 
from Table1 
WHERE cast(fldID as varchar(100))+'~'+cast(flrValue as varchar) 
NOT IN (select cast(fldID as varchar(100))+'~'+cast(flrValue as varchar) from table2) 
0

Это более простой запрос. Он возвращает все T1.fldID, которые не связаны с записями в Т2

SELECT DISTINCT T1.fldID 
FROM T1 
LEFT JOIN T2 ON T2.fldID = T1.fldPtr 
WHERE T2.fldID IS NULL 
0

Использование IN, чтобы исключить большое количество значений страшен для исполнения. Попробуйте следующее:

SELECT T1.* 
FROM T1 
    LEFT JOIN T2 ON T2.fldID = T1.fldPtr AND T1.fldValue = T2.fldvalue 
WHERE T2.fldID IS NULL 
0

(из моего комментария :) вам не нужно ссылаться на t1 снова в подзапросе. Это приведет к логике формы select all the records from t1 that don't exist in t1 ..., которая всегда пуста, как select all blue balls that are not blue, или select all odd numbers that are even ... Первый запрос должен быть:

SELECT DISTINCT fldID, fldValue 
FROM T1 
WHERE NOT EXISTS (
    SELECT * FROM T2 
    WHERE T2.fldID = T1.fldPtr 
); 

И: в исходном запросе подзапрос является коррелированы: t1 в подзапроса тениt1 в главном запросе, делая подзапрос не ссылаясь на любую таблицу или псевдоним из основного запроса: он возвращает либо True (некоторая строка существует), либо False, результат полностью не сопоставлен с строками в основном запросе. (еще одна веская причина для использовать псевдонимы вместо настоящих имен таблиц в ваших запросах)

Смежные вопросы