SQL组的时间

时间:2014-07-04 11:27:26

标签: sql sql-server group-by

我的SQL数据库中有以下表格,需要按照5分钟的最大值对其进行分组。

+------+--------+------------------+
| Path | Sample |     DateTime     |
+------+--------+------------------+
| Srv1 | 0.5    | 2014-07-04 10:48 |
| Srv1 | 0.7    | 2014-07-04 10:50 |
| Srv1 | 0.9    | 2014-07-04 10:52 |
| Srv1 | 0.6    | 2014-07-04 10:54 |
| Srv2 | 8.2    | 2014-07-04 10:48 |
| Srv2 | 7.4    | 2014-07-04 10:50 |
| Srv2 | 10.9   | 2014-07-04 10:52 |
| Srv2 | 9.9    | 2014-07-04 10:54 |
| Srv3 | 7.8    | 2014-07-04 10:48 |
| Srv3 | 1.3    | 2014-07-04 10:50 |
| Srv3 | 5.7    | 2014-07-04 10:52 |
| Srv3 | 2.4    | 2014-07-04 10:54 |
| Srv4 | 4.2    | 2014-07-04 10:47 |
| Srv4 | 3.8    | 2014-07-04 10:49 |
| Srv4 | 5.4    | 2014-07-04 10:51 |
| Srv4 | 2.4    | 2014-07-04 10:53 |
| Srv5 | 1.6    | 2014-07-04 10:48 |
| Srv5 | 1.3    | 2014-07-04 10:50 |
| Srv5 | 1.6    | 2014-07-04 10:52 |
| Srv5 | 1.3    | 2014-07-04 10:54 |
+------+--------+------------------+

下表是我的目标:

+------+--------+------------------+
| Path | Sample |     DateTime     |
+------+--------+------------------+
| Srv1 | 0.5    | 2014-07-04 10:45 |
| Srv1 | 0.9    | 2014-07-04 10:50 |
| Srv2 | 8.2    | 2014-07-04 10:45 |
| Srv2 | 10.9   | 2014-07-04 10:50 |
| Srv3 | 7.8    | 2014-07-04 10:45 |
| Srv3 | 5.7    | 2014-07-04 10:50 |
| Srv4 | 6.8    | 2014-07-04 10:45 |
| Srv4 | 5.4    | 2014-07-04 10:50 |
| Srv5 | 1.6    | 2014-07-04 10:45 |
| Srv5 | 1.6    | 2014-07-04 10:50 |
+------+--------+------------------+

我尝试了以下代码,但它并没有发出预期的结果。 GROUP BY me.Path, pd.DateTime, DATEPART(mi, pd.DateTime) % 10

我的整个SQL是:

SELECT TOP (100) PERCENT me.Path, MAX(pd.SampleValue) AS Sample, pd.DateTime
  FROM Perf.vPerfRaw AS pd
       INNER JOIN dbo.vPerformanceRuleInstance AS pri ON pri.PerformanceRuleInstanceRowId = pd.PerformanceRuleInstanceRowId
       INNER JOIN dbo.vPerformanceRule AS pr ON pr.RuleRowId = pri.RuleRowId
       INNER JOIN dbo.vManagedEntity AS me ON me.ManagedEntityRowId = pd.ManagedEntityRowId
       INNER JOIN dbo.vRule AS vr ON vr.RuleRowId = pri.RuleRowId
       INNER JOIN OperationsManager.dbo.RelationshipGenericView AS rgv ON rgv.TargetObjectDisplayName = me.Path
 WHERE (pr.CounterName = '% Processor Time')
   AND (vr.RuleDefaultName = 'Processor % Processor Time Total 2003'
       OR vr.RuleDefaultName = 'Processor % Processor Time Total Windows Server 2008'
       OR vr.RuleDefaultName = 'Processor Information % Processor Time Total Windows Server 2008 R2'
       OR vr.RuleDefaultName = 'Processor Information % Processor Time Total Windows Server 2012'
       OR vr.RuleDefaultName = 'Processor Information % Processor Time Total Windows Server 2012 R2')
   AND (rgv.SourceObjectDisplayName = 'SVM')
GROUP BY me.Path, pd.DateTime, DATEPART(mi, pd.DateTime) % 10
ORDER BY me.Path

4 个答案:

答案 0 :(得分:1)

您将pd.DateTime放在所选列和group by子句中,因此您实际上并未执行任何聚合。

有很多方法可以做到这一点,有些方法比其他方法更好,具体取决于您的数据,但请尝试以下方法:

SELECT TOP (100) PERCENT 
    me.Path, 
    MAX(pd.SampleValue) AS Sample, 
    DATEADD(MI, -(DATEPART(MI, pd.DateTime) % 5), pd.DateTime) AS PeriodStart
FROM ...
WHERE ...
GROUP BY me.Path, DATEADD(MI, -(DATEPART(MI, pd.DateTime) % 5), pd.DateTime)
ORDER BY me.Path

请注意,这仅在日期时间值中的秒数始终为0时才有效。否则,您需要一个额外的DATEADD来抵消它们。

答案 1 :(得分:0)

%是余数运算符。你想要整数除法。

select [path], MAX(sample),
    convert(time,dateadd(minute,convert(int,(CONVERT(decimal(9,4), datetime) % 1)/0.003472)*5,0)) 
from yourdata
GROUP BY Path,  convert(time,dateadd(minute,convert(int,(CONVERT(decimal(9,4), datetime) % 1)/0.003472)*5,0)) 

答案 2 :(得分:0)

试试这个

SELECT    Path, MAX(Sample), DATEADD(MINUTE, (CASE WHEN DATEPART(MINUTE, Created)%5 BETWEEN 1 AND 2 THEN 0 ELSE 5 END)-(DATEPART(MINUTE, Created))%5, Created) AS NewDate
FROM      ...
GROUP BY  Path, DATEADD(MINUTE, (CASE WHEN DATEPART(MINUTE, Created)%5 BETWEEN 1 AND 2 THEN 0 ELSE 5 END)-(DATEPART(MINUTE, Created))%5, Created)
ORDER BY  Path

答案 3 :(得分:0)

现有答案的一个问题是,由于在“源”列上使用了函数,因此没有人能够使用索引。您可以通过定义内联范围查询表的简单权宜来获得更好的性能,就像递归CTE一样。像这样:

WITH Time_Slice AS (SELECT startedAt, endedBy
                FROM (VALUES(CAST('20140704' AS DATETIME2), 
                             DATEADD(minute, 5, CAST('20140704' AS DATETIME2)))) a(startedAt, endedBy)
                UNION ALL
                SELECT endedBy, DATEADD(minute, 5, endedBy)
                FROM Time_Slice
                WHERE endedBy < DATEADD(day, 1, CAST('20140704' AS DATETIME2)))

SELECT *
FROM Time_Slice
OPTION(MAXRECURSION 0)

SQL Fiddle Results

显然,这需要在特定范围内生成 - 如果您只选择给定范围的结果,则可以将其用作开始/结束值;否则,看起来在起始部分中获取MIN()值并运行到当前时间。

然后,您可以将其作为常规表引用,如下所示:

SELECT TOP (100) PERCENT me.Path, MAX(pd.SampleValue) AS Sample, ts.startedAt
FROM Perf.vPerfRaw AS pd
INNER JOIN dbo.vManagedEntity AS me ON me.ManagedEntityRowId = pd.ManagedEntityRowId
INNER JOIN Time_Slice AS ts ON pd.DateTime >= ts.startedAt AND pd.DateTime < ts.endedBy
GROUP BY me.Path, ts.startedAt
ORDER BY me.Path