简体   繁体   中英

I need help constructing a SQL query to return counts of a column for Jan-Dec based on my Date Column

I'm not an expert at SQL and i'm not even sure if this type of query is doable.

I want to return a count(*) for each "MediaTypeID" for each Month based off of "MediaDate".

Any help would be greatly appreciated!

Thanks.

My Table looks like:

MediaTable

The Table Data looks like:

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

The query would return 12 rows of results for Jan-Dec looking like:

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

This type of data transformation is known as a PIVOT . SQL Server 2005+ has a pivot function that can be implemented:

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

See SQL Fiddle with Demo

If you have an unknown number of values that you want to transpose into columns, then you can use dynamic 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)

See SQL Fiddle with Demo

The result will look like:

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

I think this may be what you are looking for. The following will simply return the count based off the media type id, then group by year and then its month

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

In my opinion, this could be a good challenge for you to start with this code:

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
    ;

The only thing is that you should be carefull about the year value and how many years you wanna include in the output, because this result will give you the summation of all records in each month no matter which year the date of the record is. It may cause some confusion in the result.

(Remember that I always set the tab size to 8 characters in the Options of Management Studio, so I suggest you do that to see the correct style of writing T-SQL)

Hope it helps you.

Cheers

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM