Можно ли сравнить * кортежи * в предложении `WHERE` SQL-запроса?
Можно ли сравнить кортежи (спасибо, 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 ответа
Ответ Горана выглядит лучше всего для меня, и я проголосовал за него. Просто чтобы добавить еще один вариант, так как вы используете 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
Пишу
И (ВЫБЕРИТЕ HT.HeaderField1, HT.HeaderField2 FROM HeaderTable HT ГДЕ HT.HeaderKey = DT.HeaderKey) = (..., ...)
конечно возможно. По крайней мере, с Oracle и PostgreSQL
Если вы не уверены, что суб-выбор возвращает более одной строки, вы можете даже изменить =
в IN
То, что вы ищете, это внутреннее соединение:
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 = ...)
Кажется, вы пытаетесь сравнить записи, а не таблицы здесь. А на самом деле вы сравниваете результаты запросов.
Это вполне возможно с 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);