Reputation: 1084
I am currently trying to do a query like this:
(Psuedocode)
SELECT
NAME, SUM(VALUE), MONTH
FROM TABLE
WHERE MONTH BETWEEN 12 MONTHS AGO AND NOW
GROUP BY MONTH, NAME
The problem I am getting is that a name exists in a few of the months, but not all of the months, so if i filter this down to return the values for only one name, i sometimes get only 3 or 4 rows, rather than the 12 I expect to see.
My question is, is there a way to return rows, where it will still include the name, and month within the range, where the value would just be set to zero when I am missing the row from the previous result.
My first thought was to just union another select onto it, but I cant seem to get the logic to work to adhere to the group by, as well as the where clauses for limiting the names.
Upvotes: 2
Views: 1260
Reputation: 1084
I ended up implementing a left outer join similar to @paqogomez 's comment. As my team is already maintaining a time table, its very easy to get the month list for an outer join.
SELECT NAME, SUM(VALUE), TIME.MONTH
FROM (SELECT DISTINCT MONTH FROM TIME_TABLE
WHERE MONTH BETWEEN 12 MONTHS AGO AND NOW) TIME
LEFT OUTER JOIN TABLE ON (TIME.MONTH = TABLE.MONTH)
GROUP BY TIME.MONTH, NAME
Upvotes: 0
Reputation: 729
you can use something like the following table to generate all the past 12 months as separate rows:
SELECT add_months(trunc(add_months(sysdate, -12), 'MONTH'), LEVEL - 1) AS month_in_range
FROM all_objects
CONNECT BY LEVEL <= 1 + months_between(add_months(sysdate, -12), TRUNC (sysdate, 'MONTH'));
and then do an outer join between you table and this.
Upvotes: 0
Reputation: 1269503
I you have data for all months, you can take the following approach. Generate all the rows (uses a cross join
) then bring in the data you want:
select m.month, n.name, sum(t.value)
from (select distinct month from table) m cross join
(select distinct name from table) n left join
table t
on t.month = m.month and t.name = n.name
group by m.month, n.name;
This will return the missing sums as NULL
values. If you want zero, then use coalesce(sum(t.value), 0)
.
Upvotes: 3