группа по предложению с накоплением - PullRequest
3 голосов
/ 18 июня 2011

Я пытаюсь использовать group by с предложением rollup в SQL Server 2005, но у меня возникли некоторые проблемы.

Это простой дамп

create table group_roll (
id int identity,
id_name int,
fname varchar(50),
surname varchar(50),
qty int
)

go
insert into group_roll (id_name,fname,surname,qty) values (1,'john','smith',10)
insert into group_roll (id_name,fname,surname,qty) values (1,'john','smith',30)
insert into group_roll (id_name,fname,surname,qty) values (2,'frank','white',5)
insert into group_roll (id_name,fname,surname,qty) values (1,'john','smith',8)
insert into group_roll (id_name,fname,surname,qty) values (2,'frank','white',10)
insert into group_roll (id_name,fname,surname,qty) values (3,'rick','black',10)
go

Если я выполню этот простой запрос

select id_name,fname,surname,sum(qty) as tot
from group_roll
group by id_name,fname,surname

Я получаю

1   john    smith   48
2   frank   white   15
3   rick    black   10

Я бы хотел иметь

1   john    smith   48
2   frank   white   15
3   rick    black   10
Total                73

Это то, что я пытался достичь своей цели

select 
case when grouping(id_name) = 1 then 'My total' else cast(id_name as char) end as Name_id ,
fname,surname,sum(qty) as tot
from group_roll
group by id_name,fname,surname
with rollup
order by case when id_name is null then 1 else 0 end, tot desc

но мой результат

1                               john    smith   48
1                               john    NULL    48
1                               NULL    NULL    48
2                               frank   white   15
2                               frank   NULL    15
2                               NULL    NULL    15
3                               rick    black   10
3                               rick    NULL    10
3                               NULL    NULL    10
My total                         NULL   NULL   73

Где моя ошибка?

EDIT . Я мог решить мою проблему, делая

select * from (
select cast(id_name as char) as id_name,fname,surname,sum(qty) as tot
from group_roll
group by id_name,fname,surname 
union
select 'Total',null,null,sum(qty) from group_roll ) as t
order by case when id_name = 'Total' then 1 else 0 end,tot desc

но я бы хотел понять, может ли накопительный пакет решить мою проблему.

1 Ответ

3 голосов
/ 18 июня 2011

Вы не можете сделать это в самом операторе, однако вы можете отфильтровать набор ROLLUP, исключая промежуточные свертки, т. Е. Где группируются любые, но не все строки:

select
    case when grouping(id_name) = 1 then 'My total' else cast(id_name as char) end as Name_id,
    fname,
    surname,
    sum(qty) as tot
from group_roll
group by id_name, fname, surname
with rollup
having grouping(id_name) + grouping(fname) + grouping(surname) in (0 , 3)

или похоже на ваше решение, но ссылается на исходный запрос;

;with T as (
    select cast(id_name as varchar(128)) as id_name,fname,surname,sum(qty) as tot
    from group_roll
    group by id_name,fname,surname
) select * from T union all select 'Total:',null,null, SUM(tot) from T

FWIW SQL 2008 позволяет;

select
    case when grouping(id_name) = 1 then 'My total' else cast(id_name as char) end as Name_id,
    fname,
    surname,
    sum(qty) as tot
from group_roll
group by grouping sets((id_name, fname, surname), ())
...