【问题标题】:SQL Server multiple partitions by month, day and hourSQL Server 按月、日和小时划分多个分区
【发布时间】:2020-06-15 17:03:17
【问题描述】:

在 SQL Server 中,我有一个如下表:

processName   initDateTime           
processA      2020-06-15 13:31:15.330
processB      2020-06-20 10:00:30.000
processA      2020-06-20 13:31:15.330
...
and so on

我需要按 processName 分组,对于每个 processName,我需要按月 (#byMonth)、日 (#byDay) 和小时 (#byHour) 获取记录数。

最好的方法是什么?下面的东西? SQL 查询是什么?

可能的结果:

processName Month    Day  Hour  #byMonth #byDay #byHour #total(by process)
processA    January  15   17    4         3     2       7
processA    January  15   20    4         3     1       7
processA    January  20   05    4         2     3       7
processA    January  20   13    4         2     1       7
processA    March    04   05    3         2     3       7
processA    March    04   17    3         2     2       7
processA    March    15   05    3         3     3       7

...and so on for the rest of processes name

【问题讨论】:

    标签: sql sql-server group-by count window-functions


    【解决方案1】:

    我认为你想要聚合和窗口函数:

    select 
        processName,
        month(initDateTime),
        day(initDateTime),
        datepart(hour, initDateTime),
        sum(count(*)) over(partition by processName, year(initDateTime), month(initDateTime)) byMonth,
        sum(count(*)) over(partition by processName, year(initDateTime), month(initDateTime), day(initDateTime)) byDay,
        count(*) byHour
    from mytable
    group by 
        processName,
        year(initDateTime),
        month(initDateTime),
        day(initDateTime),
        datepart(hour, initDateTime)
    

    【讨论】:

    • 正是我想要的。只有一件事,你忘了在 byDay 之前加上括号。
    【解决方案2】:

    只要有可能,我喜欢将日期作为日期返回给调用者,以便他们也可以将它们作为日期处理,例如排序、转换为本地时间,甚至确保显示的语言是相关的。所以如果是我,我会这样做:

    -- sample data
    CREATE TABLE #T (processName VARCHAR(50), initDateTime  DATETIME)
    INSERT #T (processName, initDateTime)
    VALUES
        ('processA', '2020-06-15 13:31:15.330'),
        ('processB', '2020-06-20 10:00:30.000'),
        ('processA', '2020-06-20 13:31:15.330')
    
    
    SELECT  t.processName,
            i.InitHour,
            ByMonth = SUM(COUNT(*)) OVER(PARTITION BY i.InitMonth),
            ByDay = SUM(COUNT(*)) OVER(PARTITION BY i.InitDay),
            ByHour = COUNT(*)
    FROM    #T AS t
            CROSS APPLY
            (   SELECT  InitHour = DATEADD(HOUR, DATEDIFF(HOUR, 0, initDateTime), 0), 
                        InitDay = DATEADD(DAY, DATEDIFF(DAY, 0, initDateTime), 0),
                        InitMonth = DATEADD(MONTH, DATEDIFF(MONTH, 0, initDateTime), 0)
            ) AS i
    GROUP BY t.processName, i.InitHour, i.InitDay, i.InitMonth;
    

    返回:

    processName     InitHour                ByMonth ByDay   ByHour
    --------------------------------------------------------------
    processA        2020-06-15 13:00:00     3       1       1
    processA        2020-06-20 13:00:00     3       2       1
    processB        2020-06-20 10:00:00     3       2       1
    

    如果你需要SQL中的日期、月份名称等,你可以使用DATEPARTDATENAME来获取这些,但是如上所述,这在表示层中处理得更好,所以你可以处理语言环境,或特定的用户设置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 2016-08-12
      • 2017-02-01
      • 1970-01-01
      • 2016-05-26
      相关资源
      最近更新 更多