2

我正在使用以下查询从按 MeterNumber 分组的表中选择最近的和第三个最近的值。用户提供确定返回的最高值的月份和日期。

查询的目的是查看一米的水读数,看看它们在 3 个月内是否相同。如果是这样,则没有消耗发生,并且仪表可能已损坏。

我的问题是,我还想排除在 4 日、5 日、6 日……最近读取日期具有相同读数的任何仪表,因为这些仪表可能未使用。

任何帮助将不胜感激!我对此很陌生,所以也许有一种更有效/更好的方法来实现这一点。

我正在使用 MS SQL 2012。

SELECT 
MeterNumber, 
MAX(WaterRead) AS CurrentRead, 
MAX(ReadDate) AS CurrentReadDate, 
MIN(WaterRead) AS nthLastRead, 
MIN(ReadDate) AS nthLastReadDate
From
(SELECT MeterNumber, ReadDate, WaterRead
    FROM (
        SELECT MeterNumber, ReadDate, WaterRead, Rank() over (Partition BY MeterNumber ORDER BY ReadDate DESC ) AS myRank
    FROM WaterReads
) WaterReads WHERE myRank <= 3 ) a
Group By MeterNumber
Having MAX(WaterRead) - MIN(WaterRead) = 0 AND MAX(WaterRead) != 0 AND MIN(WaterRead) != 0     AND MIN(ReadDate) <> MAX(ReadDate)
AND MONTH(MAX(ReadDate)) = 6 AND DAY(MAX(ReadDate)) = 25
ORDER BY MeterNumber, CurrentReadDate

这将返回:

MeterNumber CurrentRead CurrentReadDate nthLastRead nthLastReadDate
80021139    12103       2013-06-25      12103   2013-04-24
80029512    5347        2013-06-25      5347    2013-04-24
80038245    304304      2013-06-25      304304  2013-04-24
80044119    46250       2013-06-25      46250   2013-04-24
80048357    6707        2013-06-25      6707    2013-04-24
4

1 回答 1

0

你在正确的轨道上。您可以使用 max(case when...) 来提取特定的前期进行比较。像这样:

SELECT
    meternumber,
    MAX(CASE WHEN myrank = 1 THEN readdate ELSE NULL END) curr_date,
    MAX(CASE WHEN myrank = 1 THEN waterread ELSE NULL END) curr_read,
    MAX(CASE WHEN myrank = 4 THEN readdate ELSE NULL END) ago3_date,
    MAX(CASE WHEN myrank = 4 THEN waterread ELSE NULL END) ago3_read,
    MAX(CASE WHEN myrank = 7 THEN readdate ELSE NULL END) ago6_date,
    MAX(CASE WHEN myrank = 7 THEN waterread ELSE NULL END) ago6_read
FROM
(        
    SELECT  MeterNumber, 
            ReadDate, 
            WaterRead, 
            Rank() over (Partition BY MeterNumber ORDER BY ReadDate DESC ) AS myRank
      FROM  WaterReads
            WHERE   readdate <= '20130625'
) AS a
GROUP BY
    meternumber
HAVING
    MAX(CASE WHEN myrank = 1 THEN waterread ELSE NULL END) = MAX(CASE WHEN myrank = 4 THEN waterread ELSE NULL END) 
    AND MAX(CASE WHEN myrank = 1 THEN waterread ELSE NULL END) > MAX(CASE WHEN myrank = 7 THEN waterread ELSE NULL END) 
    AND MAX(CASE WHEN myrank = 4 THEN waterread ELSE NULL END) > 0

SQLFiddle在这里

或者,更容易阅读,但有一个额外的子查询:

SELECT
    meternumber,
    curr_date,
    curr_read,
    ago3_date,
    ago3_read,
    ago6_date,
    ago6_read
FROM    
(
    SELECT
        meternumber,
        MAX(CASE WHEN myrank = 1 THEN readdate ELSE NULL END) curr_date,
        MAX(CASE WHEN myrank = 1 THEN waterread ELSE NULL END) curr_read,
        MAX(CASE WHEN myrank = 4 THEN readdate ELSE NULL END) ago3_date,
        MAX(CASE WHEN myrank = 4 THEN waterread ELSE NULL END) ago3_read,
        MAX(CASE WHEN myrank = 7 THEN readdate ELSE NULL END) ago6_date,
        MAX(CASE WHEN myrank = 7 THEN waterread ELSE NULL END) ago6_read
    FROM
    (        
        SELECT  MeterNumber, 
                ReadDate, 
                WaterRead, 
                Rank() over (Partition BY MeterNumber ORDER BY ReadDate DESC ) AS myRank
          FROM  WaterReads
                WHERE   readdate <= '20130625'
    ) AS a
    GROUP BY
        meternumber
) AS b
WHERE
    curr_read = ago3_read
    AND curr_read > ago6_read
    AND ago3_read > 0
于 2013-08-09T16:59:01.900 回答