Search code examples
mysqlsqlunionrollup

Add a row with totals for each column


I am trying to add a row to a SQL select query that contains a sum (or any other operation, such as an average, for that matter) as a last row. In this it is something similar to GROUP BY ... WITH ROLLUP.

To begin with: let's say I have a table t with fields ID, A, B and C, all of which are numbers. Also, ID is not unique, but rather a category. My SELECT query is supposed to count how many of these numbers fall within a designated range.

So, for example, the end result would be

(SELECT t.ID, a.ac, b.bc, c.cc FROM t
LEFT JOIN (SELECT COUNT(*) cc,ID FROM t WHERE A BETWEEN 2 AND 4 GROUP BY ID) AS a ON a.ID=t.ID 
LEFT JOIN (SELECT AVG(B) cc,ID FROM t WHERE B BETWEEN 19 AND 40 GROUP BY ID) AS b ON b.ID=t.ID 
LEFT JOIN (SELECT COUNT(*) cc,ID FROM t WHERE C BETWEEN 12 AND 14 GROUP BY ID) AS c ON a.ID=t.ID GROUP BY t.ID) 

union 

(select 'Overall',
 (SELECT COUNT(*) cc FROM t WHERE A BETWEEN 2 AND 4),
 (SELECT AVG(B) cc FROM t WHERE B BETWEEN 19 AND 40),
 (SELECT COUNT(*) cc FROM t WHERE C BETWEEN 12 AND 14) );

However, this solution is not ideal, for I need to re-state the conditions for A,B and C. I would like to know whether there is a simple way of accomplishing the same result specifying the conditions only once.

Thanks in advance.


Solution

  • I don't think there's a simpler solution. But I would rewrite your queries like this:

    SELECT
      t.ID,
      count(case when A between 2 and 4 then ID end),
      AVG(case when B between 19 and 40 then B end),
      COUNT(case when C between 12 and 14 then id end)
    FROM t
    GROUP BY ID
    UNION
    select
      'Overall',
      count(case when A between 2 and 4 then ID end),
      AVG(case when B between 19 and 40 then B end),
      COUNT(case when C between 12 and 14 then id end)
    FROM t