This can be simpler and faster using date_trunc()
and some simplifications:
SELECT date_trunc('month', date1)::date AS month
, sum(spending) AS sum_spending
, count(*) AS count_rows -- optional addition
FROM table
GROUP BY 1
HAVING count(*) > 1
ORDER BY 1;
Only returns the sum of spendings for months with more than one row.
If you need to display separate year and month numbers, you could use above query in a subquery, still faster:
SELECT extract(year FROM month)::int AS year
, extract(month FROM month)::int AS month
, sum_spending, count_rows
FROM (
SELECT date_trunc('month', date1)::date AS month
, sum(spending) AS sum_spending
, count(*) AS count_rows -- optional
FROM table
GROUP BY 1
HAVING count(*) > 1
ORDER BY 1
) sub;
Or extract the numbers directly like in your solution, but just use the much faster count(*)
in the HAVING
clause:
SELECT extract(year FROM date1)::int AS year
, extract(month FROM date1)::int AS month
, sum(spending) AS sum_spending
, count(*) AS count_rows -- optional
FROM table
GROUP BY 1, 2
HAVING count(*) > 1
ORDER BY 1, 2;
1, 2
are (totally optional) positional references to shorten the syntax, so we don't have to repeat the expressions in the SELECT
list. Example:
The cast to integer (::int
) is also optional. The generic return type of extract is double precision, but year and date can be cast to integer safely. Smaller, faster and more adequate.