Можно ли сравнить * кортежи * в предложении WHERE SQL-запроса? - PullRequest
6 голосов
/ 04 февраля 2011

Можно ли сравнить кортежи (спасибо, a_horse_with_no_name) в предложении WHERE SQL-запроса? Таким образом, я мог бы преобразовать это:

/* This is actually a sub-sub-sub-query in the middle *
 * of an incredibly complex stored procedure.         */
SELECT ISNULL(SUM(DT.DetailField), 0)
FROM   DetailTable DT
WHERE  DT.ForeignKey = ...
AND    EXISTS (/* I know this sub-sub-sub-sub-query *
                * will return at most one row.      */
               SELECT 'X'
               FROM   HeaderTable HT
               WHERE  HT.HeaderKey    = DT.HeaderKey
               AND    HT.HeaderField1 = ...
               AND    HT.HeaderField2 = ...)

На что-то похожее на это:

SELECT ISNULL(SUM(DetailField), 0)
FROM   DetailTable DT
WHERE  DT.ForeignKey = ...
AND    (SELECT HT.HeaderField1, HT.HeaderField2
        FROM   HeaderTable HT
        WHERE  HT.HeaderKey = DT.HeaderKey) = (..., ...)

Ответы [ 4 ]

5 голосов
/ 04 февраля 2011

То, что вы ищете, это внутреннее соединение:

SELECT ISNULL(SUM(DetailField), 0)
FROM   DetailTable DT
INNER JOIN HeaderTable HT ON HT.HeaderKey = DT.HeaderKey
WHERE  DT.ForeignKey = ...
AND    HT.HeaderField1 = ...
AND    HT.HeaderField2 = ...)
5 голосов
/ 04 февраля 2011

Запись

AND    (SELECT HT.HeaderField1, HT.HeaderField2
        FROM   HeaderTable HT
        WHERE  HT.HeaderKey = DT.HeaderKey) = (..., ...)

безусловно возможна.По крайней мере, с Oracle и PostgreSQL

Если вы не уверены, что подвыбор возвращает более одной строки, вы можете даже изменить = на IN

2 голосов
/ 04 февраля 2011

Похоже, вы пытаетесь сравнить записи не таблицы здесь. И на самом деле вы сравниваете результаты запросов.

Это вполне возможно с Oracle и MySQL. Следующий запрос действителен и выполняет задание:

SELECT (SELECT foo, bar FROM wathever) = (SELECT fuu, baz FROM another);

Он сравнивает поля одно с одним и возвращает 1, если они все совпадают (или 0, если они не совпадают). Если подзапросы возвращают более одной строки, это вызовет ошибку SQL. Это выражение может также использоваться в другом месте, как в предложениях WHERE.

Обновление для postgreSQL

Как указывал @tsionyx, в PostgreSQL подзапрос не может возвращать несколько столбцов. Возможен возврат типа значения строки:

SELECT (SELECT ROW(foo, bar) FROM wathever) = (SELECT ROW(fuu, baz) FROM another);
1 голос
/ 05 февраля 2011

Ответ Горана выглядит лучше всего для меня, и я проголосовал за него. Просто чтобы добавить еще один вариант, поскольку вы используете SQL Server, гибкий способ получения нескольких столбцов из подзапросов - outer apply. Вы можете сравнить два значения (кортеж), например:

select  *
from    SomeTable t1
outer apply
        (
        select  *
        from    SomeOtherTable t2
        where   t1.Stuff = t2.Unit
        ) sub1
outer apply
        (
        select  *
        from    YetAnotherTable t3
        where   t1.Stuff = t3.jetser
        ) sub2
where   sub1.col1 = sub2.col1
        and sub1.col2 = sub2.col2
...