I have an idea. Let's performance test the two above given solutions.-- Populate a 1,200 row calendar tableCREATE TABLE #Calendar ( FromDate DATE NOT NULL, ToDate DATE NOT NULL, YearMonth INT NOT NULL )INSERT #Calendar ( FromDate, ToDate, YearMonth )SELECT DATEADD(MONTH, m.Number, DATEADD(YEAR, y.Number, '20000101')), DATEADD(MONTH, 1 + m.Number, DATEADD(YEAR, y.Number, '20000101')), 100 * (2000 + y.Number) + m.Number + 1FROM master..spt_values AS yINNER JOIN master..spt_values AS m ON m.Type = 'P' AND m.Number BETWEEN 0 AND 11WHERE y.Type = 'P' AND y.Number BETWEEN 0 AND 99CREATE UNIQUE CLUSTERED INDEX UCX_Calendar ON #Calendar (FromDate, ToDate, YearMonth)-- Populate a 8,000,000 row orders tableCREATE TABLE #Orders ( CustomerID INT NOT NULL, OrderDate DATETIME NOT NULL, Amount MONEY NOT NULL )INSERT #Orders ( CustomerID, OrderDate, Amount )SELECT ABS(CHECKSUM(NEWID())), DATEADD(SECOND, ABS(CHECKSUM(NEWID())) % 60, DATEADD(MINUTE, ABS(CHECKSUM(NEWID())) % 52596000, '20000101')), ABS(CHECKSUM(NEWID())) / 10000EFROM master..spt_values AS v1INNER JOIN master..spt_values AS v2 ON v2.Type = 'P' AND v2.Number BETWEEN 0 AND 199INNER JOIN master..spt_values AS v3 ON v3.Type = 'P' AND v3.Number BETWEEN 0 AND 199WHERE v1.Type = 'P' AND v1.Number BETWEEN 0 AND 199CREATE UNIQUE CLUSTERED INDEX UCX_Orders ON #Orders (CustomerID, OrderDate)-- Solution by PesoSELECT DATEADD(MONTH, theMonth, 0) AS YearMonth, theAmount AS AmountFROM ( SELECT DATEDIFF(MONTH, 0, OrderDate) AS theMonth, SUM(Amount) AS theAmount FROM #Orders GROUP BY DATEDIFF(MONTH, 0, OrderDate) ) AS d/*(1200 row(s) affected)Table 'Worktable'. Scan count 0, logical reads 0.Table '#Orders'. Scan count 17, logical reads 31849. SQL Server Execution Times: CPU time = 5772 ms, elapsed time = 388 ms.*/-- Solution by CelkoSELECT c.YearMonth, SUM(o.Amount) AS AmountFROM #Calendar AS cINNER JOIN #Orders AS o ON o.OrderDate >= c.FromDate AND o.OrderDate < c.ToDateGROUP BY c.YearMonth/*(1200 row(s) affected)Table 'Worktable'. Scan count 1200, logical reads 24162377.Table '#Calendar'. Scan count 17, logical reads 13.Table '#Orders'. Scan count 1, logical reads 31849. SQL Server Execution Times: CPU time = 33025 ms, elapsed time = 31425 ms.*/DROP TABLE #Calendar, #Orders
Let's see what the results are.1) Peso uses 6 times less CPU2) Peso uses 760 times less reads3) Peso is 80 times faster
N 56°04'39.26"E 12°55'05.63"