SQL Server 2005 erro ao agrupar usando subconsulta
-
06-07-2019 - |
Pergunta
Usando o SQL Server 2005 Estou tentando grupo baseado em uma instrução case com uma subconsulta, mas eu estou recebendo um erro ( "Cada expressão GROUP BY deve conter pelo menos uma referência de coluna. "). Eu posso trabalhar em torno dela muito facilmente, mas alguém pode explicar o erro? Eu tenho uma referência de coluna para o # header.header.
create table #header (header int)
create table #detail (header int, detail int)
insert into #header values (1)
insert into #header values (2)
insert into #header values (3)
insert into #detail values (1, 1)
insert into #detail values (2, 1)
--error: Each GROUP BY expression must contain at least one column reference.
select case when exists (select 1 from #detail where #detail.header = #header.header) then 1 else 0 end hasrecords from #header
group by case when exists (select 1 from #detail where #detail.header = #header.header) then 1 else 0 end
--results I want
select hasrecords, count(*) from
(
select case when exists (select 1 from #detail where #detail.header = #header.header) then 1 else 0 end hasrecords from #header
) hasrecords
group by hasrecords
drop table #header
drop table #detail
[editar] Nota (em resposta ao comentário) correlacionados e não correlacionados subconsultas:
--correlated
select header, case when exists (select 1 from #detail where #detail.header = #header.header) then 1 else 0 end hasrecords from #header
--non-correlated
select #header.header, case when count(#detail.header) > 0 then 1 else 0 end hasrecords from #header left join #detail on #header.header = #detail.header group by #header.header
Solução
Para começar, se dermos o erro completo, deve ler-se " Cada expressão GROUP BY deve conter pelo menos uma coluna que não é uma referência externa. "
Para entender o erro, precisamos esclarecer o que se entende por uma 'referência externa'
(Nota: neste caso não tem nada a ver com o interior ou exterior junta)
interior e exteriores são em referência à consulta principal e é subconsultas.
Neste caso, o EXISTS
é a subconsulta e é um correlacionada subconsulta, pois tem uma referência externa de #header.header
, que faz referência a #header
tabela externa, enquanto que qualquer referência a #detail
seria considerado como referências internas.
Então, em essência, porque o CASE
utiliza uma subconsulta correlacionada que as referências da consulta externa, então este incêndios no estado de erro, beacuse esta mensagem de erro aparece quando você tentar usar apenas expressões em uma cláusula GROUP BY que são interpretadas como referências externas .
Subqueries pode ser usado em GROUP BY, mas não correlacionados subconsultas.
Desconcertante, o mesmo erro pode ser gerado por uma consulta não-subqueried, mais simples, como
select
case when header=1 then 1
else 0
end headeris1,
'constant'
from #header
group by case when header=1 then 1 else 0 end , 'constant'
ou mesmo substituir a constante com um @variable
Claro como lama?
Kev
Outras dicas
Você está dizendo a ele para grupo por 1 ou 0 quando você precisa dar-lhe uma coluna real para grupo por (cabeçalho), não o valor.
Então, se eu estou entendendo direito você está querendo uma lista dos cabeçalhos e uma contagem de seus registros de detalhes?
Isso pode funcionar para você?
SELECT DISTINCT h.header, COUNT(d.detail) AS detail_count
FROM #header AS h
LEFT JOIN #detail AS d ON d.header = h.header
GROUP BY h.header, d.detail
Com resultados como ...
header detail_count
1 1
2 1
3 0