2014-09-26 3 views
0

Я пытаюсь запустить запрос, который возвращает все записи в таблице, которая существует в подзапросе.MySQL WHERE EXISTS оценивает значение true для всех записей

Однако он возвращает все записи только тех, которые я ожидаю.

Вот запрос:

SELECT DISTINCT x FROM T1 WHERE EXISTS 
     (SELECT * FROM T1 NATURAL JOIN T2 WHERE T2.y >= 3.0); 

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

Но когда я запускаю весь запрос, он возвращает записи, которые не должны существовать в подзапросе.

Почему EXISTS оценивает значение true для всех записей в T1?

ответ

2

Вам нужен коррелированный подзапрос, а не соединение в подзапросе. Неясно, что право пункт корреляции, но что-то вроде этого:

SELECT DISTINCT x 
FROM T1 
WHERE EXISTS (SELECT 1 FROM T2 WHERE T2.COL = T1.COL AND T2.y >= 3.0); 

Ваш запрос имеет регулярный подзапрос. Всякий раз, когда он возвращает хотя бы одну строку, значение exists истинно. Таким образом, должна быть хотя бы одна соответствующая строка. Эта версия «логически» запускает подзапрос для каждой строки во внешнем T1.

+0

это работа !! Спасибо, я приму этот ответ, как только смогу. У меня есть некоторая путаница с коррелированными vs join. Почему разум вел себя так, как будто это было верно все время? – jor

+0

твой вел себя как истинный все время, потому что второй запрос был полностью независим, и, следовательно, что-то существовало для каждой записи в оцениваемой таблице. то есть не было способа согласования результата подзапроса с какой-либо конкретной строкой в ​​T1, поэтому все строки были возвращены. –

1

В: Почему EXISTS оценивает значение true для всех записей в T1?

A: Поскольку подзапрос возвращает строку, полностью независимую от чего-либо во внешнем запросе.

Предикат EXISTS просто проверяет, возвращает ли подзапрос строку или нет, и возвращает логическое значение ИСТИНА или ЛОЖЬ.

Вы бы получить тот же результат с:

SELECT DISTINCT x FROM T1 WHERE EXISTS (SELECT 1) 

(Единственное различие было бы, если что подзапрос не вернулся хотя бы одну строку, то вы получите строки не возвращаются во внешнем запросе .)

Нет корреляции между строками, возвращаемыми подзапросом, и строками во внешнем запросе.

Ожидает, что есть еще один вопрос, который вы хотите задать. И ответ на это действительно зависит от того, какой результат вы хотите вернуть.

Если вы желаете, чтобы вернуть строки из T1, которые имеют некоторую строку «соответствия» в T2, вы можете использовать либо NOT EXISTS (correlated subquery)

Или, вы можете также использовать операцию соединения для возврата эквивалентного результата, например, :

SELECT DISTINCT T1.x 
    FROM T1 
NATURAL 
    JOIN T2 
    WHERE T2.y >= 3.0 
+0

Спасибо! Да, увидев пример выше, я лучше понимаю, как работает EXISTS. После добавления корреляции между внешним и внутренним запросом я получил правильные результаты! – jor

+0

@JulioReyes: Я приведу пример коррелированного подзапроса, но 'NATURAL JOIN' эффективно« скрывает »имена столбцов, которые вы« сопоставляете »в' T1' и 'T2'. Мое личное предпочтение заключается в том, чтобы избежать использования 'NATURAL JOIN', потому что если он« работает », когда T1 содержит столбцы' (fa, fee, fi, fo, fum) 'и T2 содержит столбец' (doh, ray, me, fa) '... добавление другого столбца в T1 или T2, используя имя, совпадающее с именем существующего столбца в другой таблице,« сломает »запрос. Например, добавление столбца 'me' в T1 изменит то, что делает операция NATURAL JOIN. – spencer7593

+0

Кроме того, с помощью NATURAL JOIN, чтобы «выяснить», какие столбцы «сопоставляются», читателю необходимо будет сравнить определения T1 и T2, чтобы найти все столбцы с одинаковым именем. (Я предпочитаю писать свои запросы, чтобы они не «ломались», если кто-то добавляет столбец в таблицу, а также не делает его менее необходимым для того, чтобы читатель мог ознакомиться с определениями таблиц, чтобы узнать, к каким именам столбца относятся. – spencer7593

0

Он не работает, потому что не существует корреляции между внешним запросом и используемым подзапросом.Ниже есть корреляция в виде and T1.id = T2.id

SELECT DISTINCT x 
FROM T1 
WHERE EXISTS (SELECT 1 FROM T2 WHERE T2.y >= 3.0 and T1.id = T2.id) 
; 

Но, не зная данных я надеюсь, вы не должны использовать «отличный» в этом запросе, и это приведет к тому же результату:

SELECT x 
FROM T1 
WHERE EXISTS (SELECT 1 FROM T2 WHERE T2.y >= 3.0 and T1.id = T2.id) 
; 

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

SELECT DISTINCT x FROM T1 NATURAL JOIN T2 WHERE T2.y >= 3.0 
+0

Спасибо, что имеет больше смысла сейчас! Я не делал никакой корреляции. – jor

0

Вы можете использовать INNER JOIN, чтобы получить, где вы» re пытается пойти:

SELECT DISTINCT T1.X 
    FROM T1 
    INNER JOIN T2 
    ON T2.COL = T1.COL 
    WHERE T2.Y > 3.0 

Делитесь и наслаждайтесь.

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