1

考虑以下两个表:

key_names
----------------------------------------------
id | name
----------------------------------------------
1    Outside Temperature
2    Inside Temperature
3    Relative Humidity 

key_values
----------------------------------------------
id | time                    | key_id | value
----------------------------------------------
1    2013-06-04 13:20:16.347   1        50
2    2013-06-04 13:20:16.348   2        30
3    2013-06-04 13:20:16.349   3        10
4    2013-06-04 13:20:31.120   1        55
5    2013-06-04 13:20:31.122   2        29
6    2013-06-04 13:20:31.120   3        11

3 个不同键的值以 15 秒的间隔写入数据库。我希望能够以 1 分钟、5 分钟、1 小时和其他时间间隔提取值。

这是我现在间隔五分钟的内容:

SELECT time, key_name, value
FROM key_values kv
JOIN key_names kn ON kv.key_id = kn.id
WHERE (key_id = 1 OR key_id = 2 OR key_id = 3)
    AND time >= '2013-06-04 12:20:30' 
    AND time < '2013-06-04 13:20:30'
GROUP BY DATEPART(YEAR, time), DATEPART(MONTH, time), DATEPART(DAY, time),
    DATEPART(HOUR, time), (DATEPART(MINUTE, time) / 5), kv.key_id, kn.key_name
ORDER BY kv.time DESC

当然,这个查询会给我以下错误:

列 'key_values.time' 在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中。

但我不想要任何汇总数据!我只想要五分钟间隔的行的实际值。如何修复此查询?

预期结果集:(5 分钟间隔)

----------------------------------------------------
time                | key_id | value
----------------------------------------------------
2013-06-04 13:20:16   1        50
2013-06-04 13:20:16   2        30
2013-06-04 13:20:16   3        10
2013-06-04 13:15:16   1        ...
2013-06-04 13:15:16   2        ...
2013-06-04 13:15:16   3        ...
2013-06-04 13:10:16   1        ...
2013-06-04 13:10:16   2        ...
2013-06-04 13:10:16   3        ...
...                   ...      ...

对于回答我问题的其中一个人:

SELECT time, key_name, value
FROM (
        SELECT time, key_name, value, ROW_NUMBER() over (partition by convert(varchar(16), time, 121) order by time desc) as seqnum
        FROM key_values kv
        JOIN key_names kn ON kn.id = kv.tag_id
        WHERE (key_id = 1 OR key_id = 2 )
                AND time >= '2013-06-04 12:20:30' AND time < '2013-06-04 13:20:30'
) k
where seqnum = 1;


Its only returning one of the keys..

2013-06-04 12:20:59.577 Outside Temperature     45
2013-06-04 12:21:59.607 Outside Temperature     45
2013-06-04 12:22:59.637 Outside Temperature     45
2013-06-04 12:23:59.687 Outside Temperature     45
2013-06-04 12:24:59.697 Outside Temperature     46
2013-06-04 12:25:59.723 Outside Temperature     46
4

1 回答 1

5

您想使用该row_number()函数枚举每个间隔中的值。然后,只取最后一个或第一个 - 取决于您想要间隔之前的最后一个还是之前的第一个。

以下是 1 分钟间隔的示例:

select time, key_name, value
from (SELECT time, key_name, value,
             ROW_NUMBER() over (partition by key_name, convert(varchar(16), time, 121) order by time desc) as seqnum
      FROM key_values kv join
           key_names kn
           ON kv.key_id = kn.id
     ) k
where seqnum = 1;

该表达式convert(varchar(16), time, 121)将日期格式化为最接近的分钟(使用截断)。

编辑:其他增量。以下示例显示了如何在 15 分钟内执行此操作:

(partition by key_name, datediff(minute, 0, time)/15 order by . . . )

对于 5 分钟的增量,使用5代替15等等。这是计算自时间开始以来的分钟数(对数据库而言)。SQL Server 执行整数除法,因此除以整数会为时间跨度创建一个标识符。对于其他单位,您可以将 替换minutehourseconddaymonthyear

对于原始查询,我认为这convert()更容易理解。

于 2013-06-04T14:14:54.037 回答