Я наткнулся на эту загадку в комментариях здесь
CREATE TABLE r (b INT);
SELECT 1 FROM r HAVING 1=1;
SQL Server и PostgreSQL возвращают 1 строку.
MySQL и Oracle возвращают ноль строк.
Что правильно? Или оба одинаково действительны?
aggregate
sql-standard
Мартин Смит
источник
источник
SELECT COUNT(*) FROM r;
возвращает 1 строку (с0
), а неSELECT COUNT(*) FROM r GROUP BY ();
возвращает строк.SELECT 1 WHERE 1=0 HAVING 1=1;
, SQL Server и PostgreSQL по- прежнему возвращают одну строку. Oracle хочет ОТ DUAL и не возвращает строк. MySQL не компилируется ни с FRU DUAL, ни без него .SELECT 1 AS t FROM (SELECT 1) tmp WHERE 1=0 HAVING 1=1;
1-row-no-dual и возвращает 0 строк.<group by clause>
, то“GROUP BY ()”
подразумевается." Разве оба запроса не должны давать одинаковые результаты?HAVING
разному): SQl-fiddle 2: HAVINGОтветы:
По стандарту:
средства
Цитирование ISO / IEC 9075-2: 2011 7.10 Синтаксическое правило 1 (часть определения предложения HAVING):
Хорошо, так что многое довольно ясно.
Утверждение:
1=1
верно условие поиска. Я не буду приводить цитаты для этого.Сейчас
эквивалентно
Цитирование ISO / IEC 9075-2: 2011 7.10 Общее правило 1:
Логика: поскольку условие поиска всегда истинно, результатом является результат
R
, являющийся результатом группы по выражению.Ниже приводится выдержка из Общих правил 7.9 (определение GROUP BY CLAUSE)
Таким образом, мы можем сделать вывод, что
в результате получается сгруппированная таблица, состоящая из одной группы, с нулевыми строками (поскольку R пусто).
Отрывок из Общих правил 7.12, который определяет Спецификацию запроса (он же оператор SELECT):
Поэтому, поскольку таблица имеет одну группу, она должна иметь одну строку результатов.
таким образом
должен вернуть набор результатов из 1 строки.
QED
источник
Когда есть
HAVING
пункт, безWHERE
пункта:... тогда
GROUP BY ()
подразумевается. Итак, запрос должен быть эквивалентен:... который должен сгруппировать все строки таблицы в одну группу (даже если в таблице вообще нет строк - это по-прежнему одна группа из 0 строк) и вернуть 1 строку.
HAVING
этогоTrue
условие не должно иметь никакого эффекта.С другой стороны, сколько строк должен возвращать запрос, подобный этому?
Один, ноль или «ноль или один, в зависимости от того, пуста таблица или нет»?
Я думаю, что один ряд, независимо от того, сколько строк
r
.источник
Из того, что я вижу, похоже, что SQLServer и PostgerSQL вообще не заботятся о просмотре таблицы:
также возвращает только одну строку. Хотя в документации по SQLServer написано
в данном случае это не так -
WHERE 1=1
вместо того, чтобыHAVING
возвращать правильное количество строк. Я бы сказал, что это ошибка оптимизатора (или, по крайней мере, ошибка документации) ... План SQLServer показывает «Постоянное сканирование» в случае «HAVING
и сканирование таблицы» дляWHERE
...Поведение Oracle и Mysql кажется мне более логичным и правильным ...
источник
explain
«Result (lines = 1) ...» для наличия и «Seq Scan» для «WHERE», он также не смотрит в таблицу. .. Я думаю, это как-то связано с тем, что "FROM" не является обязательным в TSQL и PostgreSQL. Я знаю, что Mysql также не требует этого, но, поскольку они поддерживаютdual
, они, вероятно, анализируют запрос немного по-другому. Я согласен, это звучит как спекуляция, но я надеюсь, что это имеет смысл.