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:
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)
);
ora se volessimo sapere in un determinato periodo, con cadenza mensile, le transazioni effettuate faremmo:
codice:
SELECT YEAR(data) AS anno, MONTH(data) AS mese, SUM(importo) AS totale
FROM transazione
GROUP BY YEAR(data), MONTH(data)
ottenendo un risultato di questo tipo:
ANNO - MESE - TOTALE
2009 - 02 - 997
2009 - 03 - 1794
2009 - 04 - 300
dove il campo mese ovviamente parte dal 1 giorno del mese fino all'ultimo.

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:
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;
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.

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:
codice:
SELECT YEAR(data) AS anno, monthInterval(data, 10) AS mese, SUM(importo) AS totale
FROM transazione
GROUP BY YEAR(data), monthInterval(data, 10)
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)