Me deparei com esse quebra-cabeça nos comentários aqui
CREATE TABLE r (b INT);
SELECT 1 FROM r HAVING 1=1;
SQL Server e PostgreSQL retornam 1 linha.
MySQL e Oracle retornam zero linhas.
Qual é correto? Ou ambos são igualmente válidos?
Me deparei com esse quebra-cabeça nos comentários aqui
CREATE TABLE r (b INT);
SELECT 1 FROM r HAVING 1=1;
SQL Server e PostgreSQL retornam 1 linha.
MySQL e Oracle retornam zero linhas.
Qual é correto? Ou ambos são igualmente válidos?
Pela norma:
significa
Citação ISO/IEC 9075-2:2011 7.10 Regra de sintaxe 1 (Parte da definição da cláusula HAVING):
Ok, isso está bem claro.
Asserção:
1=1
é condição de busca verdadeira. Não fornecerei nenhuma citação para isso.Agora
é equivalente a
Citação ISO/IEC 9075-2:2011 7.10 Regra Geral 1:
Lógica: Como a condição de busca é sempre verdadeira, o resultado é
R
, que é o resultado do agrupamento por expressão.O seguinte é um trecho das Regras Gerais de 7.9 (a definição do GRUPO POR CLÁUSULA)
Assim podemos concluir que
resulta em uma tabela agrupada, consistindo em um grupo, com zero linhas (já que R está vazio).
Um trecho das Regras Gerais de 7.12, que define uma Especificação de Consulta (também conhecida como instrução SELECT):
Portanto, como a tabela possui um grupo, ela deve ter uma linha de resultado.
Desta forma
deve retornar um conjunto de resultados de 1 linha.
QED
Quando há
HAVING
cláusula, semWHERE
cláusula:... então
GROUP BY ()
está implícito. Assim, a consulta deve ser equivalente a:... que deve agrupar todas as linhas da tabela em um grupo (mesmo que a tabela não tenha nenhuma linha - ainda é um grupo de 0 linhas) e retornar 1 linha. O
HAVING
com aTrue
condição não deve ter nenhum efeito depois disso.De um ângulo diferente, quantas linhas uma consulta como esta deve retornar?
Um, zero ou "zero ou um, dependendo se a mesa está vazia ou não"?
Acho que uma linha, não importa quantas linhas
r
tenha.Pelo que vejo, parece que o SQLServer e o PostgerSQL não se incomodam em olhar para a tabela:
também retorna apenas uma linha. Mesmo que os documentos do SQLServer digam
isso não é verdade neste caso -
WHERE 1=1
em vez deHAVING
retornar o número adequado de linhas. Eu diria que é um bug do otimizador (ou pelo menos um bug da documentação) ... O plano SQLServer mostra 'Verificação constante' no caso deHAVING
e 'varredura de tabela' paraWHERE
...O comportamento do Oracle e do Mysql parece mais lógico e correto para mim ...