分组在期间

时间:2016-06-24 15:43:17

标签: sql sql-server tsql stored-procedures

我有一张数据表

[ProtocolName], [PacketsDate], [PacketsAmount], [Flows]
    'UPD' | '01/13/2016 23:55:00' | 50 | 10
    'UPD' | '01/14/2016 00:02:00' | 50 | 10
    'UPD' | '01/14/2016 00:03:00' | 50 | 10
    'UPD' | '01/14/2016 01:10:00' | 50 | 10
    'TCP' | '01/14/2016 00:00:00' | 50 | 10
    'TCP' | '01/14/2016 00:03:00' | 50 | 10
    'TCP' | '01/14/2016 00:10:00' | 50 | 10
    'IPv6'| '01/13/2016 23:30:00' | 50 | 10
    'IPv6'| '01/14/2016 00:03:00' | 50 | 10
    'IPv6'| '01/14/2016 00:45:00' | 50 | 10
    'IPv6'| '01/14/2016 00:50:00' | 50 | 10
    'IPv6'| '01/14/2016 01:35:00' | 50 | 10
    'IPv6'| '01/14/2016 01:33:00' | 50 | 10

我在存储过程中有自定义生成的表,其中包含句点

[DateFrom],             [DateTo]    
'01/13/2016 23:00:00' | '01/13/2016 23:30:00'
'01/13/2016 23:30:00' | '01/14/2016 00:00:00'
'01/14/2016 00:00:00' | '01/14/2016 00:30:00'
'01/14/2016 00:30:00' | '01/14/2016 01:00:00'
'01/14/2016 01:00:00' | '01/14/2016 01:30:00'
'01/14/2016 01:30:00' | '01/14/2016 02:00:00'

所以,结果我需要看下一栏

[DateTo], SUM([UDP_PacketsAmount]), SUM([TCP_PacketsAmount]), SUM([IPv6_PacketsAmount]), SUM([UPD_Flows]), SUM([TCP_Flows]), SUM([IPv6_Flows])    
    '01/13/2016 23:30:00' | 0   | 0  | 50  | 0  | 0  | 10 | 
    '01/14/2016 00:00:00' | 50  | 50 | 0   | 10 | 10 | 0  |
    '01/14/2016 00:30:00' | 100 | 50 | 50  | 20 | 10 | 10 |
    '01/14/2016 01:00:00' | 0   | 0  | 100 | 0  | 0  | 20 |
    '01/14/2016 01:30:00' | 50  | 0  | 0   | 10 | 0  | 0  |
    '01/14/2016 02:00:00' | 0   | 0  | 100 | 0  | 0  | 20 |

这对我来说非常困难,我不知道从哪里开始。

3 个答案:

答案 0 :(得分:2)

使用简单的CASE WHEN...END语句进行求和

SELECT DateTo,
   SUM(CASE WHEN ProtocolName='UPD' THEN PacketsAmount END) AS UDP_PacketsAmount,
   SUM(CASE WHEN ProtocolName='TCP' THEN PacketsAmount END) AS TCP_PacketsAmount,
   SUM(CASE WHEN ProtocolName='IPv6' THEN PacketsAmount END) AS IPv6_PacketsAmount,
   SUM(CASE WHEN ProtocolName='UPD' THEN Flows END) AS UPD_Flows,
   SUM(CASE WHEN ProtocolName='TCP' THEN Flows END) AS TCP_PacketsAmount,
   SUM(CASE WHEN ProtocolName='IPv6' THEN Flows END) AS IPv6_PacketsAmount
FROM TableName
Group BY  DateTo 

答案 1 :(得分:2)

您可以使用条件聚合和JOIN到句号表:

SELECT p.DateTo,
 UDP_PacketsAmount = SUM(CASE WHEN ProtocolName = 'UDP' THEN PacketsAmount END),
 TCP_PacketsAmount = SUM(CASE WHEN ProtocolName = 'TCP' THEN PacketsAmount END),
 IPv6_PacketsAmount= SUM(CASE WHEN ProtocolName = 'IPv6' THEN PacketsAmount END),
 UPD_Flows         = SUM(CASE WHEN ProtocolName = 'UDP' THEN Flows END),
 TCP_Flows         = SUM(CASE WHEN ProtocolName = 'TCP' THEN Flows END), 
 IPv6_Flows        = SUM(CASE WHEN ProtocolName = 'IPv6' THEN Flows END)  
FROM tab t
RIGHT JOIN periods p
  ON t.PacketsDate >= p.DateFrom AND t.PacketsDate < p.DateTo
GROUP BY p.DateTo
ORDER BY p.DateTo;

LiveDemo

注意:

DateFromDateTo重叠,因此我使用了[DateFrom,DateTo]范围。

如果您需要(DateFrom,DateTo),只需更改ON t.PacketsDate > p.DateFrom AND t.PacketsDate <= p.DateTo

答案 2 :(得分:1)

我使用UDF创建动态日期范围(如下所示)。我提供了给定的值,但可以使用参数,如@StartDate,@ EndDate,@ Increment

Select DateR1
      ,DateR2
      ,UDP_Packets  = SUM([UDP_PacketsAmount])
      ,UDP_Packets  = SUM([TCP_PacketsAmount])
      ,IPv6_Packets = SUM([IPv6_PacketsAmount])
      ,UPD_Flows    = SUM([UPD_Flows])
      ,TCP_Flows    = SUM([TCP_Flows])
      ,IPv6_Flows   = SUM([IPv6_Flows])
 From YourTableName A
 Join (Select DateR1=RetVal,DateR2=DateAdd(MINUTE,30,RetVal) from [dbo].[udf-Create-Range-Date]('2016-01-13 23:00:00','2016-01-14 02:00:00','MI',30)) B
   on  PacketsDate Between DateR1 and DateR2 and PacketsDate<DateR2
 Group By DateR1,DateR2
 Order By DateR1

子查询返回

DateR1                  DateR2
2016-01-13 23:00:00.000 2016-01-13 23:30:00.000
2016-01-13 23:30:00.000 2016-01-14 00:00:00.000
2016-01-14 00:00:00.000 2016-01-14 00:30:00.000
2016-01-14 00:30:00.000 2016-01-14 01:00:00.000
2016-01-14 01:00:00.000 2016-01-14 01:30:00.000
2016-01-14 01:30:00.000 2016-01-14 02:00:00.000
2016-01-14 02:00:00.000 2016-01-14 02:30:00.000

用于创建动态日期范围的UDF

CREATE FUNCTION [dbo].[udf-Create-Range-Date] (@DateFrom datetime,@DateTo datetime,@DatePart varchar(10),@Incr int)

Returns 
@ReturnVal Table (RetVal datetime)

As
Begin
    With DateTable As (
        Select DateFrom = @DateFrom
        Union All
        Select Case @DatePart
               When 'YY' then DateAdd(YY, @Incr, df.dateFrom)
               When 'QQ' then DateAdd(QQ, @Incr, df.dateFrom)
               When 'MM' then DateAdd(MM, @Incr, df.dateFrom)
               When 'WK' then DateAdd(WK, @Incr, df.dateFrom)
               When 'DD' then DateAdd(DD, @Incr, df.dateFrom)
               When 'HH' then DateAdd(HH, @Incr, df.dateFrom)
               When 'MI' then DateAdd(MI, @Incr, df.dateFrom)
               When 'SS' then DateAdd(SS, @Incr, df.dateFrom)
               End
        From DateTable DF
        Where DF.DateFrom < @DateTo
    )

    Insert into @ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)

    Return
End