Ошибка SQL Server 2005 при группировке с использованием подзапроса

StackOverflow https://stackoverflow.com/questions/1007418

Вопрос

Используя SQL Server 2005, я пытаюсь выполнить группировку на основе оператора case с подзапросом, но получаю сообщение об ошибке («Каждое выражение GROUP BY должно содержать хотя бы одну ссылку на столбец.").Я могу легко обойти это, но может ли кто-нибудь объяснить ошибку?У меня есть ссылка на столбец #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

[править] Примечание (в ответ на комментарий) коррелированные и некоррелированные подзапросы:

--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
Это было полезно?

Решение

Для начала, если мы укажем полную ошибку, она должна выглядеть следующим образом: "Каждое выражение GROUP BY должно содержать хотя бы один столбец, который не является внешней ссылкой."

Чтобы понять ошибку, нам нужно уточнить, что подразумевается под «внешняя ссылка»

(Примечание:в данном случае это не имеет ничего общего с внутренними или внешними соединениями)

А внутренний и внешний относятся к основному запросу и его подзапросам.В этом случае EXISTS это подзапрос, и это коррелированный подзапрос, поскольку он имеет внешнюю ссылку #header.header, который ссылается на внешнюю таблицу #header, тогда как любая ссылка на #detail будут рассматриваться как внутренние ссылки.

По сути, поскольку CASE использует коррелированный подзапрос, который ссылается на внешний запрос, то это вызывает состояние ошибки, поскольку это сообщение об ошибке появляется, когда вы пытаетесь использовать в предложении GROUP BY только выражения, которые интерпретируются как внешние ссылки.

Подзапросы может использоваться в GROUP BY, но не в коррелирующих подзапросах.

Как ни странно, та же ошибка может быть сгенерирована более простым запросом без подзапроса, например

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'

или даже заменить константу на @variable

Ясно как грязь?

Кев

Другие советы

Вы говорите, чтобы он группировался по 1 или 0, когда вам нужно присвоить ему фактический столбец для группировки по (заголовку), а не по значению.

Так что, если я правильно понимаю, вам нужен список заголовков и количество их подробных записей?

Это может сработать для вас?

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

С такими результатами, как ...

header   detail_count
1       1
2       1
3       0
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top