2012-08-05 67 views
2

我有這樣的表,稱爲history(日期是DD-MM-YYYY):SQL查詢組通過mount和

==================== 
| 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,11,以表現出太多,但有0(零)Qty,就像這樣:

====================== 
| 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 | 
====================== 

我怎樣才能做到這一點?

回答

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 

創建一個月表來存儲值從1到您還可以使用master..spt_values的12。相反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從月表中的值與你的表進行比對,並使用isnull函數來處理空值。

+0

什麼是「master..spt_values」過濾數據? – Kenjiro 2012-08-06 02:09:11

+0

它包含從0到2047的數字,這對於創建數字表格非常有用,正如我在上面所示。請參閱本文http://stackoverflow.com/questions/4273723/what-is-the-purpose-of-system-表表主SPT值和乜是最我。 – praveen 2012-08-06 02:28:49

+0

而不是你可以使用遞歸cte如上所示 – praveen 2012-08-06 02:29:39

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); 
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 
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