>Hai ragione quando sostieni che numero di mesi si può ricavare
>per differenza dalle date, l'ho inserita solo per semplicità.
Tutto ciò che è ridondante finisce per creare problemi.
Quei mesi non servono, quindi eliminali dalla struttura della tabella.
Inoltre mi pare di capire che l'ultima colonna sia un importo.
NON UTILIZZARE MAI dei data type approssimati come real e float per memorizzare degli importi se non vuoi introdurre degli errori di approssimazione.
Dato che nell'esempio hai inserito numeri interi, ho sostituito il data type in int.
USE tempdb;
CREATE TABLE dbo.dati(
id int NOT NULL PRIMARY KEY,
datainizio datetime NOT NULL,
datafine datetime NOT NULL,
impmensile int NOT NULL
);
INSERT dbo.dati VALUES (1, '20080101', '20081231', 2400);
INSERT dbo.dati VALUES (2, '20080101', '20080219', 200);
INSERT dbo.dati VALUES (3, '20080301', '20080430', 200);
INSERT dbo.dati VALUES (4, '20080501', '20080630', 200);
INSERT dbo.dati VALUES (5, '20080101', '20080630', 1200);
INSERT dbo.dati VALUES (6, '20090101', '20090630', 1500);
GO
CREATE FUNCTION dbo.ufn_GetData(
@From datetime,
@To datetime
)
RETURNS @Data TABLE(
datainizio datetime NOT NULL,
datafine datetime NOT NULL
)
BEGIN
WHILE @From < DATEADD(month, -1, @To)
BEGIN
INSERT @Data VALUES(@From, DATEADD(month, 1, @From) - 1);
SET @From = DATEADD(month, 1, @From);
END
INSERT @Data VALUES(@From, @To);
RETURN
END
GO
SELECT
F.*
, D.impmensile
FROM dbo.dati AS D
CROSS APPLY dbo.ufn_GetData(D.datainizio, D.datafine) AS F;
/* Output:
datainizio datafine impmensile
----------------------- ----------------------- -----------
2008-01-01 00:00:00.000 2008-01-31 00:00:00.000 2400
2008-02-01 00:00:00.000 2008-02-29 00:00:00.000 2400
2008-03-01 00:00:00.000 2008-03-31 00:00:00.000 2400
2008-04-01 00:00:00.000 2008-04-30 00:00:00.000 2400
2008-05-01 00:00:00.000 2008-05-31 00:00:00.000 2400
2008-06-01 00:00:00.000 2008-06-30 00:00:00.000 2400
2008-07-01 00:00:00.000 2008-07-31 00:00:00.000 2400
2008-08-01 00:00:00.000 2008-08-31 00:00:00.000 2400
2008-09-01 00:00:00.000 2008-09-30 00:00:00.000 2400
2008-10-01 00:00:00.000 2008-10-31 00:00:00.000 2400
2008-11-01 00:00:00.000 2008-11-30 00:00:00.000 2400
2008-12-01 00:00:00.000 2008-12-31 00:00:00.000 2400
2008-01-01 00:00:00.000 2008-01-31 00:00:00.000 200
2008-02-01 00:00:00.000 2008-02-19 00:00:00.000 200
2008-03-01 00:00:00.000 2008-03-31 00:00:00.000 200
2008-04-01 00:00:00.000 2008-04-30 00:00:00.000 200
2008-05-01 00:00:00.000 2008-05-31 00:00:00.000 200
2008-06-01 00:00:00.000 2008-06-30 00:00:00.000 200
2008-01-01 00:00:00.000 2008-01-31 00:00:00.000 1200
2008-02-01 00:00:00.000 2008-02-29 00:00:00.000 1200
2008-03-01 00:00:00.000 2008-03-31 00:00:00.000 1200
2008-04-01 00:00:00.000 2008-04-30 00:00:00.000 1200
2008-05-01 00:00:00.000 2008-05-31 00:00:00.000 1200
2008-06-01 00:00:00.000 2008-06-30 00:00:00.000 1200
2009-01-01 00:00:00.000 2009-01-31 00:00:00.000 1500
2009-02-01 00:00:00.000 2009-02-28 00:00:00.000 1500
2009-03-01 00:00:00.000 2009-03-31 00:00:00.000 1500
2009-04-01 00:00:00.000 2009-04-30 00:00:00.000 1500
2009-05-01 00:00:00.000 2009-05-31 00:00:00.000 1500
2009-06-01 00:00:00.000 2009-06-30 00:00:00.000 1500
(30 row(s) affected)
*/
DROP FUNCTION dbo.ufn_GetData;
DROP TABLE dbo.dati;
Come vedi la logica è contenuta nella Multistatement Table-valued Function dbo.ufn_GetData la quale per ogni coppia di date provvede a generare un set di righe. L'operatore CROSS APPLY permette di invocare la funzione per ogni riga restituita dalla tabella dbo.dati.
>Grazie e ciao
Prego.
Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org