0

ROLLUP allows to aggregate across multiple levels of grouping as if I UNIONed multiple simple SELECT statements.

But I want to be able to aggregate results of lower level of grouping as if I used nested SELECT statements or chain of CTEs dependent upon each other.

For example, I want to be able to count number of groups from lower level of grouping or calculate average of sums of lower level or minimum of maximums of lower level, e.t.c.

More specific example: if I have record for each auto accident in USA and I want to get not only count of accidents on each level in ROLLUP(state,county,city,zip), but also count of people (obviously each person may be involved in multiple accidents and consequently multiple records).

Is it possible to achieve that with ROLLUP ? If possible, then how ?

SQL example with results:

if object_id('accident') is not null drop table accident
create table accident(
     id int identity(1,1)
    ,state varchar(50)
    ,city varchar(50)
    ,zip varchar(50)
    ,person varchar(50)
)

insert accident(state,city,zip,person)values
 ('NY','Manhattan',10001,'John')
,('NY','Manhattan',10001,'John')
,('NY','Manhattan',10001,'Barbara')

select
    state,city,zip,person
    ,accidents=count(1)
    -- the following line causes error: Windowed functions cannot be used in the context of another windowed function or aggregate.
    --,people=sum(case when row_number()over(partition by person order by (select 0))=1 then 1 else 0 end)
from accident
group by rollup(state,city,zip,person)

;with person as (select state,city,zip,person from accident group by state,city,zip,person)
    select
        state,city,zip
        ,people=count(1)
    from person
    group by rollup(state,city,zip)

Results:

state   city    zip person  accidents
NY  Manhattan   10001   Barbara 1
NY  Manhattan   10001   John    2
NY  Manhattan   10001   NULL    3
NY  Manhattan   NULL    NULL    3
NY  NULL    NULL    NULL    3
NULL    NULL    NULL    NULL    3


state   city    zip people
NY  Manhattan   10001   2
NY  Manhattan   NULL    2
NY  NULL    NULL    2
NULL    NULL    NULL    2

See first result returns 3 accidents for each level and second returns 2. If want to get both 3 and 2 in one ROLLUP query. My problem is that windowed functions cannot be nested.

What I just asked can be achieved with this query:

;with person as (select state,city,zip,person,accidents=count(1) from accident group by state,city,zip,person)
        select
            state,city,zip
            ,accidents=sum(accidents)
            ,people=count(1)
        from person
        group by rollup(state,city,zip)

state   city    zip accidents   people
NY  Manhattan   10001   3   2
NY  Manhattan   NULL    3   2
NY  NULL    NULL    3   2
NULL    NULL    NULL    3   2

but that way of doing it requires writing CTE for each level explicitly.

I want to be able to write one query that has access to results of lower level of grouping regardless of number of grouping levels.

Tried this:

;with
    lvl as (
            select *
                    ,lvl = -1
                    ,accidents=1
                    ,people=1
                from accident
            union all
            select accident.*
                    ,lvl = grouping_id(accident.state,accident.city,accident.zip,accident.person)
                    ,accidents=sum(accidents)
                    ,people=count(1)
                from accident
                join lvl prev on prev.lvl = (grouping_id(accident.state,accident.city,accident.zip,accident.person)+1)/2-1
                group by rollup(accident.state,accident.city,accident.zip,accident.person)
        )
        select * from lvl

But got errors:

Msg 1015, Level 15, State 1, ...
An aggregate cannot appear in an ON clause unless it is in a subquery contained in a HAVING clause or select list, and the column being aggregated is an outer reference.
Msg 467, Level 16, State 1, ...
GROUP BY, HAVING, or aggregate functions are not allowed in the recursive part of a recursive common table expression 'lvl'.

Related question: recursive sql function with rollup logic?

Community
  • 1
  • 1
alpav
  • 2,972
  • 3
  • 37
  • 47
  • 4
    Please provide an example with data and desired results. – Gordon Linoff Jan 14 '14 at 00:45
  • Please read about these GROUPING sets here: http://technet.microsoft.com/en-us/library/bb522495%28v=sql.105%29.aspx – cha Jan 14 '14 at 01:11
  • How does grouping sets documentation answer my question ? Could you point or quote specific place ? – alpav Jan 14 '14 at 16:22
  • If anyone wants to see somewhat related question with DLINQ look here: http://stackoverflow.com/questions/5996403/counting-percent-of-rows-with-category-out-of-total-number-of-rows-using-dynamic – alpav Jan 14 '14 at 23:58

0 Answers0