【问题标题】:Get Previous Record by Group SQL按组 SQL 获取上一条记录
【发布时间】:2014-09-12 16:32:20
【问题描述】:

我有下表:

ID  GROUPID     ODATE       OTIME       OVALUE
1   A           2014-05-31  00:00:00    1207432.6
2   A           2014-05-31  01:00:00    1209064     
3   A           2014-05-31  02:00:00    1210698     
4   A           2014-05-31  03:00:00    1212333.3   
5   A           2014-05-31  04:00:00    1213967.7   
6   B           2014-05-31  00:00:00    2110016     
7   B           2014-05-31  01:00:00    2110016     
8   B           2014-05-31  02:00:00    2110016     
9   B           2014-05-31  03:00:00    2110016     
10  B           2014-05-31  04:00:00    2110016     
11  C           2014-05-31  00:00:00    2326592.6   
12  C           2014-05-31  01:00:00    2328088.8
13  C           2014-05-31  02:00:00    2329590.3   
14  C           2014-05-31  03:00:00    2331094.5   
15  C           2014-05-31  04:00:00    2332598

然后我运行这个语法:

SELECT 
A.ID, A.GroupID, A.oDate, A.oTime, 
A.oValue, MAX(B.oValue) AS Prev_oValue, A.oValue - MAX(B.oValue) AS oResult
FROM
Table1 AS A LEFT OUTER JOIN Table1 AS B ON B.GroupID = A.GroupID AND B.oValue < A.oValue
GROUP BY
A.ID, A.GroupID, A.oDate, A.oTime, A.oValue
ORDER BY A.GroupID, A.oDate, A.oTime

我想得到以下结果:

ID  GROUPID     ODATE       OTIME       OVALUE      PREV_OVALUE     ORESULT
1   A           2014-05-31  00:00:00    1207432.6   (null)          (null)
2   A           2014-05-31  01:00:00    1209064     1207432.6       1631.4
3   A           2014-05-31  02:00:00    1210698     1209064         1634
4   A           2014-05-31  03:00:00    1212333.3   1210698         1635.3
5   A           2014-05-31  04:00:00    1213967.7   1212333.3        1634.4
6   B           2014-05-31  00:00:00    2110016     (null)          (null)
7   B           2014-05-31  01:00:00    2110016     2110016         0
8   B           2014-05-31  02:00:00    2110016     2110016         0
9   B           2014-05-31  03:00:00    2110016     2110016         0
10  B           2014-05-31  04:00:00    2110016     2110016         0
11  C           2014-05-31  00:00:00    2326592.6   (null)          (null)
12  C           2014-05-31  01:00:00    2328088.8   2326592.6       1496.2
13  C           2014-05-31  02:00:00    2329590.3   2328088.8       1501.5
14  C           2014-05-31  03:00:00    2331094.5   2329590.3       1504.2
15  C           2014-05-31  04:00:00    2332598     2331094.5       1503.5

查看fiddle

我想要的是,根据 GroupID 列和 Order by Date and Time 列获取先前的值。在我得到之前的值之后,当前记录减去之前的值作为结果。但是出了点问题,结果很糟糕。一些记录获得先前的值,而一些记录则没有。我无法理解。

有谁知道如何做到这一点?

谢谢。

【问题讨论】:

    标签: sql sql-server sql-server-2008


    【解决方案1】:

    您可以使用带有 ROW_NUMBER() 的公用表表达式来按时间顺序对组内的每一行进行编号。获取前一个值就像将 cte 与自身连接起来一样简单,以获取具有相同 groupid 和行号少一的行。类似的东西;

    WITH cte AS (
      SELECT groupid, odate, otime, ovalue,
        ROW_NUMBER() OVER (PARTITION BY groupid ORDER BY odate, otime) rn
      FROM table1
    )
    SELECT a.groupid, a.odate, a.otime, a.ovalue, b.ovalue Prev_oValue,
           a.ovalue-b.ovalue oResult
    FROM cte a
    LEFT JOIN cte b
      ON a.groupid = b.groupid
     AND a.rn = b.rn + 1
    ORDER BY a.groupid, a.odate, a.otime
    

    An SQLfiddle to test with.

    【讨论】:

    • 这个比 Navneet Verma 答案更短,但你需要更改 oResult 计算。它应该是 a.ovalue - b.ovalue
    • @Haminteu 是的,已修复,谢谢。这就是我在第一次早上喝咖啡之前编写 SQL 得到的 :)
    • @Haminteu 至于哪个“更好”,您应该根据您的数据量对其进行测试,或者如果它们足够小而无关紧要,请使用您在阅读时更清晰的那个需要修改它:)
    • @Haminteu 你遇到了什么错误? This simple view sample 似乎有效。
    • 我的意思是查看 SQL。
    猜你喜欢
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    相关资源
    最近更新 更多