2013-05-09 140 views
1

我有表中的數據在該結構中:SQL連續列值

Region | Date  | Value 

A  | 01/01/2014 | 100 

A  | 01/20/2014 |  50 

A  | 01/02/2014 | 200 

A  | 01/05/2014 | 300 

B  | 01/01/2014 | 50 

B  | 02/15/2014 | 70 

B  | 02/25/2014 | 50 

C  | 05/02/2014 | 70 

我試圖創建這樣使用T-SQL查詢的樞軸視圖:

Region | Jan-2014 | Feb-2014 | Mar-014 | Apr-2014 | May-2014 | -> thru desired month-year 

A  | 150 | 200 | 0  |  0 | 300 | 

B  |  50 | 120 | 0  |  0 |  0 | 

C  |  0 |  0 | 0  |  0 |  70 | 

請注意,需要進行彙總 月有沒有記錄應該仍然顯示爲與零個值的列在同一個月對給定區域多個值(例如:三月和四月)

我累了使用樞軸選項,withroll等,但似乎無法得到這個工作 任何幫助,非常感謝..

謝謝。

+0

輸出是不正確的。它應該是'地區A&1月 - > 650' – 2013-05-09 08:06:03

回答

3

你之所以沒有這些月份的結果是因爲你錯過了轉入列的日期。

有幾種方法可以做到這一點。您可以硬編碼都在你查詢的IN部分的日期值,這樣的列會出現:

select Region, 
    isnull([Jan-2014], 0) [Jan-2014], isnull([Feb-2014], 0) [Feb-2014], 
    isnull([Mar-2014], 0) [Mar-2014], isnull([Apr-2014], 0) [Apr-2014], 
    isnull([May-2014], 0) [May-2014], isnull([Jun-2014], 0) [Jun-2014], 
    isnull([Jul-2014], 0) [Jul-2014], isnull([Aug-2014], 0) [Aug-2014], 
    isnull([Sep-2014], 0) [Sep-2014], isnull([Oct-2014], 0) [Oct-2014], 
    isnull([Nov-2014], 0) [Nov-2014], isnull([Dec-2014], 0) [Dec-2014] 
from 
(
    select left(datename(month, t.date), 3) +'-' 
      + cast(year(t.date) as char(4)) monthYear, 
    t.region, 
    t.value 
    from yt t 
) src 
pivot 
(
    sum(value) 
    for monthYear in ([Jan-2014], [Feb-2014], [Mar-2014], [Apr-2014], 
        [May-2014], [Jun-2014], [Jul-2014], [Aug-2014], 
        [Sep-2014], [Oct-2014], [Nov-2014], [Dec-2014]) 
) piv; 

SQL Fiddle with Demo

另一種方法是創建一個可用於查詢的日期表。創建完成後,您可以使用LEFT JOIN添加到您的表格,以便返回您想要顯示的所有日期。你可以創建一個遞歸查詢來在你的PIVOT查詢中生成這個列表,或者用一個日期列表填充一個表格。遞歸查詢將類似於此:

;with dates (startDate, endDate) as 
(
    select min(date), cast('2014-12-31' as date) 
    from yt 
    union all 
    select dateadd(m, 1, startDate), enddate 
    from dates 
    where month(startDate) + 1 <= month(enddate) 
) 
select startDate 
from dates; 

請參閱SQL Fiddle with Demo。如果你加入這對你的支點,那麼查詢將是:

select * 
from 
(
    select left(datename(month, d.startdate), 3) +'-' 
      + cast(year(d.startdate) as char(4)) monthYear, 
    t.region, 
    t.value 
    from dates d 
    left join yt t 
    on month(d.startdate) = month(t.date) 
    and year(d.startdate) = year(t.date) 
) src 
pivot 
(
    sum(value) 
    for monthYear in ([Jan-2014], [Feb-2014], [Mar-2014], [Apr-2014], 
        [May-2014], [Jun-2014], [Jul-2014], [Aug-2014], 
        [Sep-2014], [Oct-2014], [Nov-2014], [Dec-2014]) 
) piv 
where region is not null; 

SQL Fiddle with Demo。您可以將此作爲您的PIVOT查詢的一部分,但仍需要手動編碼PIVOT的IN子句中的所有日期。

我在猜測你想使用這個查詢的動態SQL版本,所以日期會根據你的需要而改變。動態版本將爲:

DECLARE @cols AS NVARCHAR(MAX), 
    @colsNull AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX), 
    @startdate datetime = '2014-01-01', 
    @enddate datetime = '2014-12-01' 

;with dates (startDate, endDate) as 
(
    select @startdate, @enddate 
    from yt 
    union all 
    select dateadd(m, 1, startDate), enddate 
    from dates 
    where dateadd(m, 1, startDate) <= enddate 
) 
select @cols = STUFF((SELECT ',' + QUOTENAME(left(datename(month, d.startdate), 3) +'-' 
                 + cast(year(d.startdate) as char(4))) 
        from dates d 
        -- where startdate >= '2014-01-01' and startdate <= '2014-06-01' 
        group by d.startdate 
        order by d.startdate 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,''), 
    @colsNull = STUFF((SELECT ', isnull(' + QUOTENAME(left(datename(month, d.startdate), 3) +'-' 
                 + cast(year(d.startdate) as char(4)))+', 0) as '+QUOTENAME(left(datename(month, d.startdate), 3) +'-' 
                 + cast(year(d.startdate) as char(4))) 
        from dates d 
        -- where startdate >= '2014-01-01' and startdate <= '2014-06-01' 
        group by d.startdate 
        order by d.startdate 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 
from dates 

set @query = 'SELECT region, ' + @colsNull + ' from 
      (
        select left(datename(month, t.date), 3) +''-'' 
          + cast(year(t.date) as char(4)) monthYear, 
        t.region, 
        t.value 
        from yt t 
      ) x 
      pivot 
      (
       sum(value) 
       for monthyear in (' + @cols + ') 
      ) p ' 

execute(@query); 

請參閱SQL Fiddle with Demo。此版本使用遞歸CTE生成將在動態sql字符串中使用的日期列表。即使您的數據表可能在所顯示的月份中不存在,您仍然會有一個新列。

這給出了一個結果:

| REGION | JAN-2014 | FEB-2014 | MAR-2014 | APR-2014 | MAY-2014 | JUN-2014 | JUL-2014 | AUG-2014 | SEP-2014 | OCT-2014 | NOV-2014 | DEC-2014 | 
---------------------------------------------------------------------------------------------------------------------------------------------- 
|  A |  650 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 | 
|  B |  50 |  120 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 | 
|  C |  0 |  0 |  0 |  0 |  70 |  0 |  0 |  0 |  0 |  0 |  0 |  0 | 
+0

謝謝!你對我的數據情況產生了積極的影響。 也可以將來自兩個樞軸查詢的結果合併?查詢將具有相同的列。感謝您的幫助 – user2365233 2013-05-10 17:26:59

+0

@ user2365233您可以看看使用UNION – Taryn 2013-05-10 17:31:16

+0

嗨 我正在尋找使用您建議的數據透視表查詢來創建視圖,並且由於變量而無法保存視圖。有沒有其他的方法來創建一個產生相同結果的視圖? – user2365233 2013-05-13 21:21:09