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
Était-ce utile?

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top