2013-01-22 38 views
1

我不是SQL專家,我甚至不確定這種查詢類型是否可行。我需要幫助構建一個SQL查詢來根據我的日期列返回Jan-Dec的列計數

我想根據「MediaDate」爲每個月返回每個「MediaTypeID」的計數(*)。

任何幫助將不勝感激!

謝謝。

我的表是這樣的:

MediaTable

表中的數據是這樣的:

1 | 1 | Funny Cat Video  | 2006-01-25 00:00:00.000 
2 | 1 | Funny Dog Video  | 2006-01-20 00:00:00.000 
3 | 2 | Angry Birds Game | 2006-03-13 00:00:00.000 
4 | 4 | Blonde Joke   | 2006-03-16 00:00:00.000 
5 | 3 | Goofy Clown Picture | 2006-02-27 00:00:00.000 
6 | 2 | Racing Game   | 2006-02-10 00:00:00.000 
7 | 1 | Star Wars Video  | 2006-07-15 00:00:00.000 

查詢將返回12行的結果爲一月至十二月的看起來像:

Month | MediaTypeID1Count | MediaTypeID2Count | MediaTypeID3Count | MediaTypeID4Count 
Jan | 400    | 255    | 15    | 65 
Feb | 100    | 25    | 75    | 35 
Mar | 320    | 155    | 50    | 99 
Apr | 56    | 0     | 98    | 313 
+0

首先'由MediaTypeID組成,month(MediaDate)'然後'pivot'它 –

回答

4

這種類型的數據轉換被稱爲一個PIVOT計數,然後它的一個月。 SQL Server的2005+具有可實現的旋轉功能:

select month, 
    [1] MediaType1_count, 
    [2] MediaType2_count, 
    [3] MediaType3_count, 
    [4] MediaType4_count 
from 
(
    select 
    mediatypeid, 
    datename(m, mediadate) Month, 
    datepart(m, mediadate) monnum 
    from yourtable 
) src 
pivot 
(
    count(mediatypeid) 
    for mediatypeid in ([1], [2], [3], [4]) 
) piv 
order by monnum 

SQL Fiddle with Demo

如果你有一個未知的數字,要轉成列的值,那麼你可以使用動態SQL:

DECLARE @cols AS NVARCHAR(MAX), 
    @colNames AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(mediatypeid) 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 


select @colNames = STUFF((SELECT distinct ', ' + QUOTENAME(mediatypeid) +' as MediaType' + cast(mediatypeid as varchar(50))+'_Count' 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT month,' + @colNames + ' from 
      (
       select mediatypeid, 
        datename(m, mediadate) Month, 
        datepart(m, mediadate) monnum 
       from yourtable 
      ) x 
      pivot 
      (
       count(mediatypeid) 
       for mediatypeid in (' + @cols + ') 
      ) p 
      order by monnum' 

execute(@query) 

SQL Fiddle with Demo

結果將類似於:

| MONTH | MEDIATYPE1_COUNT | MEDIATYPE2_COUNT | MEDIATYPE3_COUNT | MEDIATYPE4_COUNT | 
---------------------------------------------------------------------------------------- 
| January |    2 |    0 |    0 |    0 | 
| February |    0 |    1 |    1 |    0 | 
| March |    0 |    1 |    0 |    1 | 
|  July |    1 |    0 |    0 |    0 | 
+0

這很完美。非常感謝! – Maddhacker24

+0

@ Maddhacker24樂意幫忙。 :) – Taryn

-1

在我看來,這對您來說可能是一個很好的挑戰與此代碼:

Declare @T Table (
    MediaID  BigInt Primary Key Identity(1, 1) 
, MediaTypeID BigInt 
, MediaTitle Nvarchar(50) 
, MediaDate DateTime 
); 

Insert @T (
    MediaTypeID 
, MediaTitle 
, MediaDate 
) Select 1 
    , 'Funny Cat Video' 
    , '2006-01-25 00:00:00.000' 
Union 
    Select 1 
    , 'Funny Dog Video' 
    , '2006-01-20 00:00:00.000' 
Union 
    Select 2 
    , 'Angry Birds Game' 
    , '2006-03-13 00:00:00.000' 
Union 
    Select 4 
    , 'Blonde Joke' 
    , '2006-03-16 00:00:00.000' 
Union 
    Select 3 
    , 'Goofy Clown Picture' 
    , '2006-02-27 00:00:00.000' 
Union 
    Select 2 
    , 'Racing Game' 
    , '2006-02-10 00:00:00.000' 
Union 
    Select 1 
    , 'Star Wars Video' 
    , '2006-07-15 00:00:00.000' 
; 

Select Month.Title 
, Count(Type01_Result.MediaID) As MediaTypeID_1 
, Count(Type02_Result.MediaID) As MediaTypeID_2 
, Count(Type03_Result.MediaID) As MediaTypeID_3 
, Count(Type04_Result.MediaID) As MediaTypeID_4 
    From (
     Select 1  As Id 
     , 'Jan'  As Title 
    Union 
     Select 2 
     , 'Feb' 
    Union 
     Select 3 
     , 'March' 
    Union 
     Select 4 
     , 'April' 
    Union 
     Select 5 
     , 'May' 
    Union 
     Select 6 
     , 'June' 
    Union 
     Select 7 
     , 'July' 
    Union 
     Select 8 
     , 'Aug' 
    Union 
     Select 9 
     , 'Sept' 
    Union 
     Select 10 
     , 'Nov' 
    Union 
     Select 11 
     , 'Oct' 
    Union 
     Select 12 
     , 'Dec' 
    ) As Month 
    Left Outer Join 
     @T As Type01_Result 
    On Type01_Result.MediaTypeID   = 1 
    And DatePart(Month, Type01_Result.MediaDate) = Month.Id 
    Left Outer Join 
     @T As Type02_Result 
    On Type02_Result.MediaTypeID   = 2 
    And DatePart(Month, Type02_Result.MediaDate) = Month.Id 
    Left Outer Join 
     @T As Type03_Result 
    On Type03_Result.MediaTypeID   = 3 
    And DatePart(Month, Type03_Result.MediaDate) = Month.Id 
    Left Outer Join 
     @T As Type04_Result 
    On Type04_Result.MediaTypeID   = 4 
    And DatePart(Month, Type04_Result.MediaDate) = Month.Id 
    Group By Month.Title 
    ; 

的唯一的事情是,你應該小心約一年價值,以及如何多年你想在輸出中包括的,因爲這樣的結果會給你的所有記錄的總和每個月沒有問題是記錄日期的哪一年。結果可能會造成一些混淆。

(請記住,我總是設置標籤大小爲8個字符Management Studio中的選項,所以我建議你這樣做,看到寫T-SQL的正確的樣式)

希望它可以幫助你。

乾杯

+0

這是一個數據透視查詢的完美例子。使用你的代碼,他需要不斷添加這條語句,每次添加一行。我會檢查不可避免的@BlueFeet答案,以更好地感受如何做到這一點。 – Zane

+0

@Zane因爲他是T-SQL的新手,所以我認爲PIVOT子句在第一步中可能太難理解了,但是這個代碼和PIVOT會產生相同的輸出。每當有新的價值出現時,你都會改變陳述的正確性,我試圖幫助提問者更好地理解而不是使用代碼。無論如何,謝謝你的觀點。 – Rikki

0

我認爲這可能是你在找什麼。下面將簡單地返回逐年基於關閉的媒體類型ID,然後組

Select MediaTypeID, datepart(year, MediaDate), datepart(month, MediaDate), count(*) 
From Media 
Group by MediaTypeID, datepart(year, MediaDate), datepart(month, MediaDate)