SQL Server - 如何在列中给定条件检索单行?

时间:2015-12-18 16:14:26

标签: sql-server

我从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,我如何检索每个生成器存储的最新数据样本?

1 个答案:

答案 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
;

第二个例子可以重新格式化为子查询。