Ошибка SQL Server 2005 при группировке с использованием подзапроса - PullRequest
0 голосов
/ 17 июня 2009

Использование 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

Ответы [ 2 ]

3 голосов
/ 17 июня 2009

Для начала, если мы дадим полную ошибку, он должен прочитать " Каждое выражение 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

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

Кев

0 голосов
/ 17 июня 2009

Вы говорите, чтобы он группировался по 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
...