在SQL Server 2000中,我需要根据客户的订单列出临时表中的年份,月份。
如果月份不存在,我仍然需要列出年,月,0.00美元。
在SQL Server 2000中执行此操作的最佳方法是什么?
01/01/2010
到07/01/2010
会产生:
__Year__, __Month__ , __Billed__
2010,1,$5000.00
2010,2,$6000.00
2010,3,$8000.00
2010,4,$0.00
2010,5,$4000.00
2010,6,$4500.00
使用此代码:
select grp.* from
(
select year(orderdate) as yr,
month(orderdate) as mn,
sum(billed)
from Orders
group by year(orderdate), month(orderdate), billed
) grp
order grp.yr, grp.mn
是否有一个简单的解决方案,可以不跳过没有结算的月份并添加$ 0.00?
答案 0 :(得分:5)
2005年以上(对不起,我错过了2000年的要求):
DECLARE @Orders TABLE(OrderDate DATETIME, billed INT);
INSERT @Orders SELECT '20100104', 500
UNION SELECT '20100106', 700;
DECLARE
@year INT,
@end_month TINYINT;
SELECT
@year = 2010,
@end_month = 7;
WITH s(n) AS
(
SELECT TOP (@end_month) ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.objects ORDER BY [object_id]
),
m(s) AS
(
SELECT DATEADD(MONTH, n-1, DATEADD(YEAR, @year-1900, 0))
FROM s
)
SELECT
[Year] = @year,
[Month] = MONTH(m.s),
Billed = COALESCE(SUM(t.billed), 0)
FROM m
LEFT OUTER JOIN @Orders AS t
ON t.OrderDate >= m.s
AND t.OrderDate < DATEADD(MONTH, 1, m.s)
GROUP BY
MONTH(m.s)
ORDER BY [Year], [Month];
对于2000年来说,它只是略有不同:
CREATE TABLE #Orders(OrderDate DATETIME, billed INT);
INSERT #Orders SELECT '20100104', 500
UNION SELECT '20100106', 700;
DECLARE
@year INT,
@end_month TINYINT;
SELECT
@year = 2010,
@end_month = 7;
SELECT
[year] = @year,
[month] = MONTH(m.s),
billed = COALESCE(SUM(t.billed), 0)
FROM
(
SELECT s = DATEADD(MONTH, n-1, DATEADD(YEAR, @year-1900, 0)) FROM
(
SELECT DISTINCT TOP 12 n = number
FROM master..spt_values
WHERE number BETWEEN 1 AND @end_month
ORDER BY number
)
AS s
) AS m
LEFT OUTER JOIN #Orders AS t
ON t.OrderDate >= m.s
AND t.OrderDate < DATEADD(MONTH, 1, m.s)
GROUP BY MONTH(m.s);
现在我承认我没有2000个实例可以方便地进行测试 - 这只是袖手旁观。
答案 1 :(得分:3)
创建一个包含0到100,000或其他数字的数字表。
然后是这样的:
DECLARE @StartDate AS DATE
DECLARE @EndDate AS DATE
SELECT YEAR(DATEADD(m, Numbers.N, @StartDate))
,MONTH(DATEADD(m, Numbers.N, @StartDate))
,ISNULL(OrderSummary.Billed, 0) AS Billed
FROM Numbers
LEFT JOIN (
SELECT year(orderdate), month(orderdate), sum(billed)
FROM Orders
GROUP by year(orderdate), month(orderdate)
) AS OrderSummary (Yr, Mn, Billed)
ON YEAR(DATEADD(m, Numbers.N, @StartDate)) = OrderSummary.Yr
AND MONTH(DATEADD(m, Numbers.N, @StartDate)) = OrderSummary.Mn
WHERE Numbers.N < DATEDIFF(m, @StartDate, @EndDate)
2005年使用常用表格表达式稍微容易一些。