SQL获取行值之间的差异?

时间:2013-01-04 07:38:48

标签: sql sql-server

我有以下代码

SELECT MRT.sno, MRT.TypeName, MR.Adate, MAX(MRD.Value) AS Value
FROM MeterReadings MR 
INNER JOIN MeterReadingDetails MRD ON MRD.ReadingId = MR.sno
INNER JOIN MeterReadingTypes MRT ON MRT.sno = MRD.ReadingTypeId
WHERE MRT.sno IN (7,10,11)
GROUP BY MRT.sno,MRT.TypeName,MR.Adate
ORDER BY MR.Adate DESC

结果

sno TypeName                Adate                   Value

11  Toplam Kapasitif        2013-01-04 00:00:00     33,313
7   Toplam                  2013-01-04 00:00:00     7819,33
10  Toplam Reaktif          2013-01-04 00:00:00     640,492
11  Toplam Kapasitif        2013-01-03 00:00:00     33,276
7   Toplam                  2013-01-03 00:00:00     7805,934
10  Toplam Reaktif          2013-01-03 00:00:00     639,862

我想要一个名为“OldValue”的附加列。 OldValue Column显示前一天的值,如下所示(上例中的最后三行)

33,276
7805,934
639,862
null
null
null

我该怎么做?可能有一个类似的例子给我指路。

提前致谢...

更新

事实上,我写了类似的东西

SELECT MRT.sno, MRT.TypeName, MR.Adate, MAX(MRD.Value) AS Value, 

(SELECT Value From
    (SELECT TOP 1 XMR.Adate,XMRD.ReadingTypeId,MAX(XMRD.Value) AS Value 
    FROM MeterReadings XMR,MeterReadingDetails XMRD 
    WHERE XMRD.ReadingId = XMR.sno AND XMRD.ReadingTypeId = MRT.sno AND XMR.Adate<MR.Adate 
    GROUP BY XMR.Adate,XMRD.ReadingTypeId 
    ORDER BY XMR.Adate DESC) AS TBL
) AS OldValue

FROM MeterReadings MR 
INNER JOIN MeterReadingDetails MRD ON MRD.ReadingId = MR.sno
INNER JOIN MeterReadingTypes MRT ON MRT.sno = MRD.ReadingTypeId
WHERE MRT.sno IN (7,10,11)
GROUP BY MRT.sno,MRT.TypeName,MR.Adate

但我不知道,这是最好的方式吗?

1 个答案:

答案 0 :(得分:1)

如果您使用的是SQL Server 2012,则可以使用新的LAG analytical function

  

SQL Server 2012引入了新的分析函数LEAD()和LAG()。   此函数访问后续行(对于潜在客户)和   不使用a的同一结果集中的前一行(用于滞后)   自我加入。

您的陈述将变为

SELECT  *, LAG(Value) OVER (PARTITION BY sno ORDER BY Adate DESC)
FROM    (
          SELECT  MRT.sno, MRT.TypeName, MR.Adate, MAX(MRD.Value) AS Value, 
          FROM    MeterReadings MR 
                  INNER JOIN MeterReadingDetails MRD ON MRD.ReadingId = MR.sno
                  INNER JOIN MeterReadingTypes MRT ON MRT.sno = MRD.ReadingTypeId
          WHERE   MRT.sno IN (7,10,11)
          GROUP BY
                  MRT.sno,MRT.TypeName,MR.Adate
        ) q
ORDER BY
        Adate DESC

使用SQL Server 2005/2008,我会将语句写为

;WITH q AS (
  SELECT  MRT.sno, MRT.TypeName, MR.Adate, MAX(MRD.Value) AS Value, rn = ROW_NUMBER() OVER (PARTITION BY MRT.sno ORDER BY MR.Adate DESC)
  FROM    MeterReadings MR 
          INNER JOIN MeterReadingDetails MRD ON MRD.ReadingId = MR.sno
          INNER JOIN MeterReadingTypes MRT ON MRT.sno = MRD.ReadingTypeId
  WHERE   MRT.sno IN (7,10,11)
  GROUP BY
          MRT.sno,MRT.TypeName,MR.Adate
)
SELECT  q1.*, q2.Value
FROM    q q1
        LEFT OUTER JOIN q q2 ON q2.sno = q1.sno AND q2.rn = q1.rn + 1

修改

使用这些解决方案之一的主要区别在于,您的解决方案必须为每个记录检索以前的结果,这是一项昂贵的操作,而此解决方案本质上可以加入两个完整的(相同的)数据集。