views:

12

answers:

1

I'm constructing a SQL query for a business report. I need to have both subtotals (grouped by file number) and grand totals on the report.

I'm entering unknown SQL territory, so this is a bit of a first attempt. The query I made is almost working. The only problem is that the entries are being grouped -- I need them separated in the report.

Here is my sample data:

FileNumber        Date   Cost   Charge
         3   Dec 22/09      5       10
         3   Jan 13/10      6       15
        3B   Mar 28/10      1        3
        3B   Mar 28/10      5       10

When I run this query

SELECT
    CASE
        WHEN (GROUPING(FileNumber) = 1) THEN NULL
        ELSE FileNumber
    END AS FileNumber,
    CASE
        WHEN (GROUPING(Date) = 1) THEN NULL
        ELSE Date
    END AS Date,
    SUM(Cost) AS Cost,
    SUM(Charge) AS Charge

    FROM SubtotalTesting
    GROUP BY FileNumber, Date WITH ROLLUP
    ORDER BY
        (CASE WHEN FileNumber IS NULL THEN 1 ELSE 0 END), -- Put NULLs after data
        FileNumber,
        (CASE WHEN Date IS NULL THEN 1 ELSE 0 END), -- Put NULLs after data
        Date

I get the following:

FileNumber        Date  Cost  Charge
         3   Dec 22/09     5      10
         3   Jan 13/10     6      15
         3        NULL    11      25
        3B   Mar 28/10     6      13 <--
        3B        NULL     6      13
      NULL        NULL    17      38

What I want is:

FileNumber        Date  Cost  Charge
         3   Dec 22/09     5      10
         3   Jan 13/10     6      15
         3        NULL    11      25
        3B   Mar 28/10     1       3 <--
        3B   Mar 28/10     5      10 <--
        3B        NULL     6      13
      NULL        NULL    17      38

I can clearly see why the entries are being grouped, but I have no idea how to separate them while still returning the subtotals and grand total.

I'm a bit green when it comes to doing advanced SQL queries like this, so if I'm taking the wrong approach to the problem by using WITH ROLLUP, please suggest some preferred alternatives -- you don't have to write the whole query for me, I just need some direction. Thanks!

+1  A: 
WITH    SubtotalTesting (FileNumber, Date, Cost, Charge) AS
        (
        SELECT  '3', CAST('2009-22-12' AS DATETIME), 5, 10
        UNION ALL
        SELECT  '3', '2010-13-06', 6, 15
        UNION ALL
        SELECT  '3B', '2010-28-03', 1, 3
        UNION ALL
        SELECT  '3B', '2010-28-03', 5, 10
        ),
        q AS (
        SELECT  *,
                ROW_NUMBER() OVER (ORDER BY filenumber) AS rn
        FROM    SubTotalTesting
        )
SELECT  rn,
        CASE
                WHEN (GROUPING(FileNumber) = 1) THEN NULL
                ELSE FileNumber
        END AS FileNumber,
        CASE
                WHEN (GROUPING(Date) = 1) THEN NULL
                ELSE Date
        END AS Date,
        SUM(Cost) AS Cost,
        SUM(Charge) AS Charge
FROM    q
GROUP BY
        FileNumber, Date, rn WITH ROLLUP
HAVING  GROUPING(rn) <= GROUPING(Date)
ORDER BY
        (CASE WHEN FileNumber IS NULL THEN 1 ELSE 0 END),
        FileNumber,
        (CASE WHEN Date IS NULL THEN 1 ELSE 0 END),
        Date
Quassnoi
(Stupid me.) I was just trying this by using `UNION ALL` on the source table with `SELECT ... SUM(Cost) ...` -- is your solution more efficient than that?
Jon Seigel
@JonS: `UNION` would require two passes so yes, this solution is more efficient.
Quassnoi
This worked great! Thank you very much.
Jon Seigel