Salve raga,
in questi ultimi giorni mi son trovato di fronte la necessità di raggruppare delle tuple di una tabella in base ad "anno" e "mese" di una data.
Per fornirvi un esempio più comprensibile mettiamo caso che abbiamo una serie di transazioni memorizzate in una tabella, banalmente, così strutturata:
ora se volessimo sapere in un determinato periodo, con cadenza mensile, le transazioni effettuate faremmo:codice:CREATE TABLE transazione ( id VARCHAR(32) NOT NULL, tipo ENUM('aaa', 'bbb', 'ccc', 'ddd', 'eee') NOT NULL DEFAULT 'aaa', importo DECIMAL(8, 2) NOT NULL, data TIMESTAMP NOT NULL, PRIMARY KEY (id) );
ottenendo un risultato di questo tipo:codice:SELECT YEAR(data) AS anno, MONTH(data) AS mese, SUM(importo) AS totale FROM transazione GROUP BY YEAR(data), MONTH(data)
dove il campo mese ovviamente parte dal 1 giorno del mese fino all'ultimo.ANNO - MESE - TOTALE
2009 - 02 - 997
2009 - 03 - 1794
2009 - 04 - 300
La questione è: e se noi volessimo raggruppare i mesi in un intervallo che non necessariamente parte dal primo giorno?
Mettiamo che a noi interessi dal 5 del mese fino al 5 (escluso) del mese successivo?!
Come dovremmo agire?
Beh non so se può servire a qualcun altro o se ho scritto un post inutile ma io ho risolto creandp una STORED FUNTION, monthInterval(), alla quale vengono passati due parametri ovvero la "data" (che è il campo data della nostra tabella) ed il giorno del mese da cui cominciare il raggruppamento.
La funzione è questa:
ovviamente la funzione ritorna un intero di due cifre che è il mese di appartenenza in quel range di raggruppamento. La funzione presi in ingresso la data ed il giorno da cui cominciare verifica se il giorno della data (2009-03-25 10:00:00) è maggiore o uguale al giorno in cui cominciare il raggruppamento; se si allora restituira il mese corretto della data se invece il giorno della data è minore del giorno da cui cominciare il raggruppamento vorrà dire che questa data va raggruppata insieme al mese precedente.codice:DELIMITER // CREATE FUNCTION monthInterval(d TIMESTAMP, starterDay INT(2)) RETURNS INT(2) BEGIN DECLARE giorno INT(2); DECLARE mese INT(2); SET giorno = DAY(d); SET mese = MONTH(d); IF giorno >= starterDay THEN RETURN mese; ELSE RETURN (mese-1); END IF; END;
Esempio:
2009-03-15
2009-03-27
2009-04-05
2009-04-16
impostando come starterDay il giorno 10 avremo questo risultato:
2009-03-15 -----> Mese 3 (poichè 2009-03-10 <= 2009-03-15 < 2009-04-09)
2009-03-27 -----> Mese 3 (poichè 2009-03-10 <= 2009-03-27 < 2009-04-09)
2009-04-05 -----> Mese 3 (poichè 2009-03-10 <= 2009-04-05 < 2009-04-09)
2009-04-16 -----> Mese 4 (poichè 2009-03-10 <= 2009-04-09 < 2009-04-16)
in questo modo possiamo raggruppare per intervalli di date che non cominciano necessariamente dal primo giorno in questo modo:
con questa query si comincerà il raggruppamento partendo dal giorno 10 di ogni mese (dal 10 gennaio al 9 febbraio, dal 10 febbraio al 9 marzo, etc)codice:SELECT YEAR(data) AS anno, monthInterval(data, 10) AS mese, SUM(importo) AS totale FROM transazione GROUP BY YEAR(data), monthInterval(data, 10)

Rispondi quotando