我从SQL Server中的一个非常长的表中得到了一个相当简单(我想)的数据请求。
表TMLogs
包含来自连接到发电机的机械传感器的数千个数据样本。这些发生器连接到传感器,提供关键生成器性能组件数据的快照:RPM,温度,采样时间等。数据快照每5秒获取一次,然后存储在SQL Server数据库中。发电机处于不同的时区,时钟非常准确(+/- 10)分钟。
列看起来像这样:
Generator Name | Generator State | Fuel Tank Reading | Output (watts) | Sample Time (YYYY-DD-MM HH:MM:SS) | Engine Temp (F°) | Output Descriptor|....
我的目标是仅检索 每个生成器提供的最新样本。
选择TOP
X值仅给出东部时区的生成器,或者具有超出官方时间的系统时钟的生成器。
那么,根据标准Generator Name
,我如何检索每个生成器存储的最新数据样本?
答案 0 :(得分:3)
您可以采取以下两种方法。两者都使用此处定义的样本数据:
-- Let's create a sample table to experiment with.
DECLARE @Sample TABLE
(
GeneratorId INT,
SampleTime DATETIME,
Measure1 INT
)
;
-- Populate it.
INSERT INTO @Sample
(
GeneratorId,
SampleTime,
Measure1
)
VALUES
(1, '2015-01-01 09:00:00.000', 100),
(1, '2015-01-01 09:05:00.000', 90),
(2, '2015-09-01 10:00:00.000', 100),
(2, '2015-09-01 10:05:00.000', 90)
;
第一个示例使用ROW_NUMBER。这个窗口函数非常适合顺序编号记录。在这种情况下,为每个生成器分配最新的样本1.
/* The inner query ranks our records.
* The outer query filters for the most recent.
* Windowed functions cannot be used in the where clause, hence the need for a subquery.
*/
SELECT
*
FROM
(
/* ROW_NUMBER assigns a rank to each record.
* Each GeneratorId is ranked separately, thanks
* to the PARTITION BY.
*/
SELECT
ROW_NUMBER() OVER(PARTITION BY GeneratorId ORDER BY SampleTime) AS RowNum,
GeneratorId,
SampleTime,
Measure1
FROM
@Sample
) AS r
WHERE
RowNum = 1
;
或者您可以使用CTE。这允许我们首先通过生成器找到最新的样本。然后过滤那些。
/* We can also use a CTE to achive the same result.
* You could just as easily make the CTE a subquery
* in the main body.
*/
WITH MostRecent AS
(
/* This CTE finds the most recent sample for each
* generator. This is used to filer the main query.
*/
SELECT
GeneratorId,
MAX(SampleTime) AS MaxSampleTime
FROM
@Sample
GROUP BY
GeneratorId
)
SELECT
*
FROM
@Sample AS s
INNER JOIN MostRecent AS mr ON mr.GeneratorId = s.GeneratorId
AND mr.MaxSampleTime = s.SampleTime
;
第二个例子可以重新格式化为子查询。