Reputation: 353
CREATE TEMPORARY TABLE
CREATE TEMP TABLE total(
gid SERIAL,
zoom smallint NOT NULL,
point integer NOT NULL,
size integer NOT NULL
);
INSERT DATA
INSERT INTO total(zoom, point, size) VALUES(9,51,21);
INSERT INTO total(zoom, point, size) VALUES(9,75,45);
INSERT INTO total(zoom, point, size) VALUES(9,74,34);
INSERT INTO total(zoom, point, size) VALUES(10,75,4);
INSERT INTO total(zoom, point, size) VALUES(10,72,63);
INSERT INTO total(zoom, point, size) VALUES(10,85,22);
COUNTING POINTS, ADDING UP SIZE based on ZOOM
SELECT zoom,
count(*) AS point,
SUM(size) AS size
FROM total
GROUP BY zoom
ORDER BY zoom;
Result:
zoom | point | size
------+-------+------
9 | 3 | 100
10 | 3 | 89
(2 rows)
QUESTION
How can I return total of each column?
Wanted result:
zoom | point | size
------+-------+------
9 | 3 | 100
10 | 3 | 89
------+-------+------
Total | 6 | 189
Upvotes: 5
Views: 9051
Reputation:
The way to simulate a rollup is to simply run a second query that does the rollup. However all values in a column must have the same data type. As you want to display the label 'Total'
you need to convert the number zoom
from the base query to a text as well:
But as you want to sort by the actual zoom value, you also need to keep the integer value in the result.
The sort_order
is necessary to make sure that rows from the first part of the union actually stay "at the top"
select zoom, point, size
FROM (
SELECT zoom::text as zoom,
zoom as zoom_value,
count(*) AS point,
SUM(size) AS size,
1 as sort_order
FROM total
GROUP BY zoom
UNION ALL
SELECT 'Total',
null,
count(*) AS point,
SUM(size) AS size,
2 as sort_order
FROM total
) t
order by sort_order, zoom_value;
This returns:
zoom | point | size
------+-------+-----
9 | 3 | 100
10 | 3 | 89
Total | 6 | 189
With an up-to-date Postgres version you could do the following:
SELECT case when grouping(zoom) = 1 then 'Total' else zoom::text end,
count(*) AS point,
SUM(size) AS size
FROM total
GROUP BY rollup (zoom)
order by zoom;
Upvotes: 10