Erreur SQL Server 2005 lors du regroupement à l'aide d'une sous-requête
-
06-07-2019 - |
Question
Utilisation de SQL Server 2005 J'essaie de regrouper en fonction d'une instruction case avec une sous-requête, mais j'obtiens une erreur (" Chaque expression GROUP BY doit contenir au moins une référence de colonne. ") Je peux y remédier assez facilement, mais quelqu'un peut-il expliquer l'erreur? J'ai une référence de colonne à # 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
[edit] Note (en réponse au commentaire) sous-requêtes corrélées et non corrélées:
--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
La solution
Pour commencer, si nous donnons l'erreur complète, il convient de lire " Chaque expression GROUP BY doit contenir au moins une colonne qui n'est pas une référence externe. "
Pour comprendre l'erreur, nous devons clarifier le sens de l'expression "référence externe"
.(Remarque: dans ce cas, cela n'a rien à voir avec des jointures internes ou externes)
inner et outer font référence à la requête principale et à ses sous-requêtes.
Dans ce cas, EXISTS
est la sous-requête et il s'agit d'une sous-requête corrélée , car sa référence externe est # header.header
, qui référence la table externe #header
, alors que toute référence à #detail
sera considérée comme une référence interne.
Donc, en substance, étant donné que CASE
utilise une sous-requête corrélée faisant référence à la requête externe, cela déclenche l'état d'erreur, car ce message d'erreur apparaît lorsque vous essayez d'utiliser uniquement des expressions dans GROUP BY. clause interprétée comme une référence externe.
Les sous-requêtes peuvent être utilisées dans GROUP BY, mais pas les sous-requêtes corrélées.
De manière confuse, la même erreur peut être générée par une requête plus simple, sans sous-requête, telle que
.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 même remplacer la constante par un @variable
Effacer comme de la boue?
Kev
Autres conseils
Vous lui dites de grouper par 1 ou 0 lorsque vous devez lui donner une colonne à regrouper par (en-tête), pas de valeur.
Donc, si je comprends bien, vous voulez une liste des en-têtes et un décompte de leurs enregistrements détaillés?
Cela peut fonctionner pour vous?
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
Avec des résultats tels que ...
header detail_count
1 1
2 1
3 0