Grupowanie po dacie - miesiące

0

Cześć,
Przypuszczam, że podobnych tematów jest w internecie tysiące, ale dość trudno cokolwiek wygrzebać.

Jeżeli mam tabelę zawierającą atrybuty **data **i wartość i takie w niej dane:
2020.01.01 - 5
2020.01.18 - 18
2020.05.05 - 12
2020.10.10 - 18
2020.10.12 - 20

To
SELECT MONTH(data), SUM(wartosc) FROM tabela GROUP BY MONTH(data) ORDER BY MONTH(data)

zwróci nam :
1 - 23
5 - 12
10 - 38

W jaki sposób mógłbym pozyskać coś takiego?
1 - 23
2 - 0
3 - 0
4 - 0
5 - 12
6 - 0
7 - 0
8 - 0
9 - 0
10 - 38
11 - 0
12 - 0

Czy muszę robić paskudne zapytanie na 12 warunków czy mogę jakoś sprytnie 'dodać' w wyniku te brakujące miesiące?

Pozdrawiam,

2
with r as (select 1 m
union all
select m+1 from r where m<12
)

select 
m
, SUM(wartosc)
from r
left join  tabela on MONTH(tabela.data) = r.m
group by
m
1

Prawdopodobnie szukasz terminu "data warehousing", tam się natkniesz na pojęcia takie jak "fact table" i "dimension table". Dimensionem może być na przykład - tak jak u Ciebie - seria miesięcy. Nie jest niczym dziwnym w tym przypadku tabela "Miesiace" która zawiera po prostu liczby od 1 do 12 żeby można było się zjoinować. Jeśli potrzebujesz generować regularne raporty lub kostkę OLAP to jest to najprostsze i najszybsze rozwiązanie. Swoją drogą dobrze jeśli "tablica faktów" (czyli tablica ze spłaszczonymi przeprocesowanymi wstępnie danymi) ma już rozdzieloną datę na poszczególne składowe jeśli chcesz żeby to naprawdę szybko chodziło. Możesz też wykorzystać date dimension - https://radacad.com/do-you-need-a-date-dimension

Tak więc - jeśli chcesz się pobawić lub jednorazowo wygenerować sobie raport to wykorzystaj CTE tak jak w przykładzie powyżej.
Jeśli chcesz to zrobić optymalnie i czytelnie to po prostu zmaterializuj sobie tablicę z liczbami 1 - 12 lub skorzystaj z date dimension

0

Dziękuję chłopaki za obszerną pomoc. Muszę zapoznać się z proponowanym przez @obscurity rozwiązaniem, ponieważ - nie wiedzieć czemu - rozwiązanie od @Panczo po implementacji w mój kod zwraca dokładnie takie samo rozwiązanie (bez 12 miesięcy) jak wcześniej.

1

Aby stwierdzic co robisz nie tak, musialbys pokazać kod po implementacji, obstawiam, że nie robisz poprawnie left join

Można też bez CTE i rekurencji:

select 
m
, SUM(wartosc)
from  (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) as r(m)
left join  tabela on MONTH(tabela.data) = r.m
group by
m

1 użytkowników online, w tym zalogowanych: 0, gości: 1