Я потратил некоторое время на поиск такого файла и в итоге сам его создал, его можно получить здесь:
https://github.com/grammakov/us_cities_and_states/tree/ мастер
Чтобы ответить на ваш вопрос об использовании ключевого слова EXISTS , вот пример запроса, который использует предикат EXISTS, основанный на запросе, который в настоящее время задан в вашем вопрос.
SELECT t.* FROM tblTransaction t WHERE EXISTS ( SELECT 1 FROM tblTenantTransCode ttc JOIN tblCheckbookCode cc ON (cc.ID = ttc.CheckbookCode AND cc.Description='Rent Income') WHERE ttc.ID = t.TransactionCode )
Дополнительные сведения:
Мы все понимаем, что существует множество операторов SQL, которые возвращают набор результатов, который соответствует указанным требованиям. И, вероятно, будут различия в наблюдаемой производительности этих запросов. Производительность особенно зависит от СУБД, режима оптимизатора, плана запроса и статистики (количества строк и распределения значений данных).
Одним из преимуществ EXISTS
является то, что он дает понять, что мы не заинтересованы в возврате каких-либо выражений из таблиц в подзапросе. Он служит для логического отделения подзапроса от внешнего запроса, чего не делает JOIN
.
Еще одно преимущество использования EXISTS
заключается в том, что исключается возврат повторяющихся строк, которые могут быть (мог бы быть) возвращен, если бы мы вместо этого использовали JOIN
.
Предикат EXISTS
можно использовать для проверки существования любой связанной строки в дочерней таблице без требуя соединения. В качестве примера следующий запрос возвращает набор всех заказов, у которых есть хотя бы один связанный line_item:
SELECT o.* FROM order o WHERE EXISTS ( SELECT 1 FROM line_item li WHERE li.order_id = o.id )
Обратите внимание, что подзапросу не нужно находить ВСЕ соответствующие элементы строки, ему нужно найти только одну строку, чтобы удовлетворить условие. (Если бы мы записали этот запрос как JOIN
, то мы бы возвращали повторяющиеся строки всякий раз, когда в заказе было более одной позиции.)
Предикат NOT EXISTS
также является полезно, например, для возврата набора заказов, которые не не имеют связанных line_items.
SELECT o.* FROM order o WHERE NOT EXISTS ( SELECT 1 FROM line_item li WHERE li.order_id = o.id )
Конечно, NOT EXISTS
- лишь одна из альтернатив. Эквивалентный набор результатов может быть получен с использованием ВНЕШНЕГО соединения и теста IS NULL (при условии, что у нас есть хотя бы одно выражение, доступное из таблицы line_item, которое НЕ NULL)
SELECT o.* FROM order o LEFT JOIN line_item li ON (li.order_id = o.id) WHERE li.id IS NULL
Кажется, есть много дискуссий (относительно ответов на исходный вопрос) о необходимости использования предиката IN
или необходимости использования JOIN
.
Эти конструкции являются альтернативными, но не обязательными. Требуемый набор результатов может быть возвращен запросом без использования IN
и без использования JOIN
. Набор результатов может быть возвращен запросом, который использует предикат EXISTS
. (Обратите внимание, что в заголовке вопроса OP действительно говорилось о том, как использовать ключевое слово EXISTS
.)
Вот еще один альтернативный запрос (это не мой первый выбор), но возвращенный набор результатов удовлетворяет заданные требования:
SELECT t.* FROM tblTransaction t WHERE EXISTS ( SELECT 1 FROM tblTenantTransCode ttc WHERE ttc.ID = t.TransactionCode AND EXISTS ( SELECT 1 FROM tblCheckbookCode cc WHERE cc.ID = ttc.CheckbookCode AND cc.Description = 'Rent Income' ) )
Прежде всего, запрос должен возвращать правильный набор результатов, который удовлетворяет заданным требованиям, учитывая все возможные наборы условий.
Некоторые из запросов, представленных здесь в качестве ответов, НЕ возвращают запрошенный набор результатов, а если и возвращают, то делают это случайно. Некоторые запросы будут работать, если мы заранее предположим что-то о данных, например, некоторые столбцы будут UNIQUE
и NOT NULL
.
Различия в производительности
Иногда запрос с предикат EXISTS
не будет работать так же хорошо, как запрос с предикатом JOIN
или IN
. В некоторых случаях он может работать лучше. (С предикатом EXISTS
подзапрос должен найти только одну строку, удовлетворяющую условию, а не ВСЕ совпадающие строки, как того требует JOIN
.)
Эффективность различных параметров запроса лучше всего оценивается наблюдением.
Различия в производительности
Иногда запрос с предикатом EXISTS
не будет работать так же хорошо, как запрос с предикатом JOIN
или IN
. В некоторых случаях он может работать лучше. (С предикатом EXISTS
подзапрос должен найти только одну строку, удовлетворяющую условию, а не ВСЕ совпадающие строки, как того требует JOIN
.)
Эффективность различных параметров запроса лучше всего оценивается наблюдением.
Различия в производительности
Иногда запрос с предикатом EXISTS
не будет работать так же хорошо, как запрос с предикатом JOIN
или IN
. В некоторых случаях он может работать лучше. (С предикатом EXISTS
подзапрос должен найти только одну строку, удовлетворяющую условию, а не ВСЕ совпадающие строки, как того требует JOIN
.)
Эффективность различных параметров запроса лучше всего оценивается наблюдением.
Попробуйте следующее:
SELECT
tblTenantTransCode.ID
FROM tblCheckbookCode
INNER JOIN tblTenantTransCode ON tblCheckbookCode.ID=tblTenantTransCode.CheckbookCode
WHERE tblCheckbookCode.Description = 'Rent Income'
Убедитесь, что вы проиндексировали tblCheckbookCode.Description
.
Вам нужно использовать предложение IN:
select id from tblTenantTransCode
where tblTenantTransCode.CheckbookCode in
(select id from tblCheckbookCode
where description = 'rent income')
внутреннее соединение, вероятно, будет лучшим решением, хотя ...
select ttc.id from tblTenantTransCode as ttc
inner join tblCheckbookCode as tcc
on ttc.CheckBookId = tcc.id
where tcc.description = 'rent income'
Вы описываете внутреннее соединение.
select tc.id
from tblTenantTransCode tc
inner join tblCheckbookCode cc on tc.CheckbookCode = cc.CheckbookCode
РЕДАКТИРОВАТЬ: Это все еще внутреннее соединение. Я пока не вижу причин для использования предложения IN.
select *
from tblTransaction t
inner join tblTenantTransCode tc on tc.id = t.TransactionCode
inner join tblCheckbookCode cc on cc.id = tc.CheckbookCode
where cc.description = 'Rent Income'
РЕДАКТИРОВАТЬ: Если вы должны использовать предикат EXISTS для решения этой проблемы, см. Ответ @ spencer7953. Однако из того, что я вижу, вышеприведенное решение проще, и есть предположения об уникальности, основанные на том факте, что «Подзапрос» работает для вас (это не было бы в 100% случаев, если бы в этой таблице не было уникальности. ). Я также обращаюсь к
. Теперь я хочу выбрать Все транзакции. где их код транзакции соответствует идентификатору, возвращенному в подзапросе
моего ответа. Если бы запрос был чем-то вроде этого:
Теперь я хочу выбрать Все транзакции , когда любой код транзакции соответствует идентификатору, возвращенному в подзапросе.
Я бы использовал EXISTS, чтобы увидеть, существует ли какой-либо код транзакции в дочерней таблице, и вернуть каждую строку или ни одной, в зависимости от ситуации.
Учитывая ваш полный запрос, этот запрос приведет вас туда, куда вам нужно, с помощью одного соединения.
Объединение отфильтровывает любую транзакцию, не имеющую кода транзакции «Доход от аренды». Он возьмет всю запись из первой таблицы, построит подмножество второй таблицы (предложение WHERE ограничивает записи), а затем отфильтрует первую таблицу, в которой эта таблица вычисляет условие соединения.
SELECT
t.*
FROM
tblTransaction t
INNER JOIN tblTenantTransCode c ON
t.TransactionCode = c.ID
INNER JOIN tblCheckbookCode chk ON
c.CheckbookCode = chk.ID
WHERE
chk.Description = 'Rent Income'
Изменить: еще одно примечание: Избегайте использования SELECT * - всегда указывайте столбцы. Edit Dos: я пропустил, что было три таблицы. Исправлено! Спасибо, Спенсер!