简体   繁体   English

我需要帮助构建一个SQL查询,以根据我的日期列返回Jan-Dec列的计数

[英]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. 我不是SQL的专家,我甚至不确定这种类型的查询是否可行。

I want to return a count(*) for each "MediaTypeID" for each Month based off of "MediaDate". 我想根据“MediaDate”为每个月的每个“MediaTypeID”返回一个计数(*)。

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: 该查询将返回Jan-Dec的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

This type of data transformation is known as a PIVOT . 这种类型的数据转换称为PIVOT SQL Server 2005+ has a pivot function that can be implemented: SQL Server 2005+具有可以实现的pivot功能:

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 请参阅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: 如果要将未知数量的值转置为列,则可以使用动态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 请参阅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 以下内容将根据媒体类型ID返回计数,然后按年份分组,然后按月分组

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) (请记住,我总是在Management Studio的选项中将选项卡大小设置为8个字符,因此我建议您这样做以查看正确的编写T-SQL的样式)

Hope it helps you. 希望它能帮到你。

Cheers 干杯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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