我有这个名为history
的表(日期在DD-MM-YYYY中):
====================
| Buy | Qty |
====================
| 01-01-2012 | 1 |
| 01-01-2012 | 1 |
| 01-02-2012 | 1 |
| 01-03-2012 | 1 |
| 01-05-2012 | 1 |
| 01-07-2012 | 1 |
| 01-12-2012 | 1 |
====================
注意:在第4,6,8,9,10,11个月没有购买。
如果我跑:
SELECT MONTH(buy) AS day, YEAR(buy) as year, SUM(qty)
FROM history
GROUP BY MONTH(buy),YEAR(buy)
我得到了这个结果:
======================
| Month | Year | Qty |
======================
| 01 | 2012 | 2 |
| 02 | 2012 | 1 |
| 03 | 2012 | 1 |
| 05 | 2012 | 1 |
| 07 | 2012 | 1 |
| 12 | 2012 | 1 |
======================
我想要显示4,6,8,9,10,18个月,但Qty
为0(零),如下所示:
======================
| Month | Year | Qty |
======================
| 01 | 2012 | 2 |
| 02 | 2012 | 1 |
| 03 | 2012 | 1 |
| 04 | 2012 | 0 |
| 05 | 2012 | 1 |
| 06 | 2012 | 0 |
| 07 | 2012 | 1 |
| 08 | 2012 | 0 |
| 09 | 2012 | 0 |
| 10 | 2012 | 0 |
| 11 | 2012 | 0 |
| 12 | 2012 | 1 |
======================
我该怎么做?
答案 0 :(得分:1)
您可以使用整数查找表。
我在这种情况下使用的是通过CTE生成号码的功能/程序(以下示例)
其余的是使用结果数字作为月份创建日期 - 然后加入上面的结果。
declare @min int
declare @max int
set @min = 1
set @max = 12
;
with numbers(n) as
(
select @min as n
union all
select n + 1
from numbers
where n + 1 <= @max
)
select row_number() over (order by n) [row], n
from numbers option(maxrecursion 0);
答案 1 :(得分:1)
试试这个:
Declare @Sample table
(Buy datetime ,Qty int)
Insert into @Sample values
( '01-01-2012' ,1),
('01-01-2012',1 ),
('01-02-2012',1 ),
('01-03-2012',1 ),
('01-05-2012',1 ),
('01-07-2012',1 ),
('01-12-2012',1 )
;with cte as
(
select top 12 row_number() over(order by t1.number) as N
from master..spt_values t1
cross join master..spt_values t2
)
select t.N as month,
isnull(datepart(year,y.buy),'2012') as Year,
sum(isnull(y.qty,0)) as Quantity
from cte t
left join @Sample y
on month(convert(varchar(20),buy,103)) = t.N
group by y.buy,t.N
创建一个Month表来存储从1到12的值。而不是master..spt_values,你也可以使用sys.all_objects
select row_number() over (order by object_id) as months
from sys.all_objects
或使用递归cte生成月份表
;with cte(N) as
(
Select 1
union all
Select 1+N from cte where N<12
)
Select * from cte
然后使用Left join将month表中的值与表进行比较,并使用isnull
函数来处理空值。
答案 2 :(得分:1)
下面的代码可以帮助您,您也可以按年过滤数据
SELECT MonthYearTable.Month , MonthYearTable.Year, ISNULL(SUM(qty),0)
FROM history
Right JOIN (SELECT Month, Year FROM (SELECT 1 AS Month
Union SELECT 2
Union SELECT 3
Union SELECT 4
Union SELECT 5
Union SELECT 6
Union SELECT 7
Union SELECT 8
Union SELECT 9
Union SELECT 10
Union SELECT 11
Union SELECT 12) AS MonthTable
INNER JOIN (SELECT DISTINCT YEAR(buy) AS year FROM history) YearTable ON 1=1
) AS MonthYearTable ON Month(history.buy) = MonthYearTable.Month AND Year(history.buy) = MonthYearTable.Year
GROUP BY MonthYearTable.Month, MonthYearTable.Year
ORDER BY MonthYearTable.Year, MonthYearTable.Month
答案 3 :(得分:0)
试试这个:
CREATE TABLE history(Buy datetime,Qty int)
INSERT INTO history
VALUES('01-01-2012',1),
('01-01-2012',1),
('01-02-2012',1),
('01-03-2012',1),
('01-05-2012',1),
('01-07-2012',1),
('01-12-2012',1)
Declare @mindate datetime
Declare @maxdate datetime
select @mindate=MIN(convert(datetime,buy,103)),@maxdate=MAX(convert(datetime,buy,103)) from history
select datepart(month,a.dt) as month,datepart(year,a.dt) as year,isnull(SUM(qty),0) as Quantity
from
(select DATEADD(mm,number,convert(varchar(10),@mindate,103)) as dt from master..spt_values
where type='p' and DATEADD(mm,number,convert(varchar(10),@mindate,103)) <= convert(varchar(10),@maxdate,103)
) a left join history h
on DATEPART(month,a.dt) = DATEPART(month,convert(varchar(10),h.Buy ,103))
group by a.dt
order by a.dt