Подтвердить что ты не робот

Как использовать ключевое слово T-SQL Exists?

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

подзапросов:

SELECT ID 
FROM tblTenantTransCode 
WHERE
    tblTenantTransCode.CheckbookCode = 
      (SELECT ID FROM tblCheckbookCode WHERE Description = 'Rent Income')

Это вернет все коды транзакций с кодом чековой книжки, который соответствует рентабельным доходам

Теперь я хочу выбрать "Все транзакции", где их код транзакции соответствует идентификатору, возвращенному в подзапросе. Я получил это далеко, но SQL Server жалуется на синтаксическую ошибку. Как я могу это сделать?

Полный запрос:

SELECT * 
FROM tblTransaction
WHERE
    tblTransaction.TransactionCode IN 
      (SELECT ID FROM tblTenantTransCode 
       WHERE tblTenantTransCode.CheckbookCode = 
           (SELECT ID FROM tblCheckbookCode WHERE Description = 'Rent Income'))

Таблицы:

tblCheckbookCode  
   ID  
   Description  
   Other Info  

tblTenantTransCode  
   ID  
   CheckbookCode <-- fk we're looking for   
                     in the tblCheckbookCode.   
                     We're selecting only checkbook codes   
                     that have the Description 'Rent Income'  
   Other Info  

tblTransactions  
   ID  
   TransactionCode <-- fk to tenant transaction code.   
                       We're looking for an ID that is returned   
                       in the above query/join  
4b9b3361

Ответ 1

Чтобы ответить на вопрос об использовании ключевого слова 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, тогда мы возвращали бы повторяющиеся строки всякий раз, когда у заказа было более одной позиции.)

Предикат

A NOT EXISTS также полезен, например, для возврата набора заказов, у которых не есть любые связанные строки_имя.

    SELECT o.*
      FROM order o
     WHERE NOT EXISTS
           ( SELECT 1
               FROM line_item li
              WHERE li.order_id = o.id
           )

Конечно, NOT EXISTS - это всего лишь одна альтернатива. Эквивалентный набор результатов может быть получен с использованием соединения OUTER и теста 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.)

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

Ответ 2

Вы описываете внутреннее соединение.

select tc.id 
from tblTenantTransCode tc 
   inner join tblCheckbookCode cc on tc.CheckbookCode = cc.CheckbookCode

EDIT: Это еще внутреннее соединение. Я еще не вижу причины использовать предложение 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'

EDIT: Если вы должны использовать предикат EXISTS для решения этой проблемы, см. ответ @spencer7953. Однако из того, что я вижу, решение выше проще и есть предположения о уникальности, основанные на том, что для вас работает "Подзапрос" (это не было бы в 100% случаев, если бы в этой таблице не было уникальности). Я также обращаюсь к

Теперь я хочу выбрать "Все транзакции" где их код транзакции соответствует идентификатору, возвращенному в подзапросе

в моем ответе. Если запрос был чем-то вроде этого:

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

Я бы использовал EXISTS, чтобы увидеть, существует ли какой-либо код транзакции в дочерней таблице и возвращать каждую строку или нет, если это необходимо.

Ответ 3

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

В этом объединении отфильтровывается любая транзакция, у которой нет кода транзакции "Доход от аренды". Он возьмет всю запись из первой таблицы, построит подмножество второй таблицы (предложение 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: Я пропустил, что было три стола. Исправленный! Спасибо, spencer!

Ответ 4

Попробуйте следующее:

SELECT
    tblTenantTransCode.ID 
    FROM tblCheckbookCode 
        INNER JOIN tblTenantTransCode ON tblCheckbookCode.ID=tblTenantTransCode.CheckbookCode
    WHERE tblCheckbookCode.Description = 'Rent Income'

Убедитесь, что вы указали tblCheckbookCode.Description.

Ответ 5

Вам нужно использовать предложение "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'