具有相同ID的多行之间的SQL差异

时间:2018-05-03 18:45:07

标签: sql sql-server sql-server-2012 inner-join aggregate-functions

SQL Sever 2012

原始数据

ID   VAL   Time
+---+----+---------------------+
| 2 |  1 | 2015-05-09 12:54:39 |
| 3 | 10 | 2015-05-09 12:54:39 |
| 2 |  1 | 2015-05-09 12:56:39 |
| 3 | 10 | 2015-05-09 12:56:39 |
| 2 |  5 | 2015-05-09 13:48:30 |
| 3 | 16 | 2015-05-09 13:48:30 |
| 2 |  7 | 2015-05-09 15:01:09 |
| 3 | 20 | 2015-05-09 15:01:09 |
+---+----+---------------------+ 

我有一张表,其中VAL正在及时增加。我想操纵数据来显示每个ID随着时间的推移增加了多少VAL。所以Val在Time2 - Val at Time1

理想的结果:

ID   VALI   Time
+---+----+---------------------+
| 2 |  0 | 2015-05-09 12:56:39 |
| 3 |  0 | 2015-05-09 12:56:39 |
| 2 |  4 | 2015-05-09 13:48:30 |
| 3 |  6 | 2015-05-09 13:48:30 |
| 2 |  2 | 2015-05-09 15:01:09 |
| 3 |  4 | 2015-05-09 15:01:09 |
+---+----+---------------------+ 
到目前为止

代码:

select
t1.Time,t1.[ID],t2.[VAL]-t1.[VAL] AS [ValI]
from #tempTable t1
inner join #tempTable t2 ON t1.[ID]=t2.[ID]
AND t1.[Time]<t2.[Time]

我需要计算当前时间戳与当前时间戳之前的时间之间的差异,而不是当前时间戳之前的所有时间戳。截至目前,当VAL没有改变时,我得到了很多重复值。

5 个答案:

答案 0 :(得分:2)

你可以使用它。

DECLARE @MyTable TABLE (ID INT,   VAL INT,  [Time] DATETIME)
INSERT INTO @MyTable VALUES
(2,  1 ,'2015-05-09 12:54:39'),
(3, 10 ,'2015-05-09 12:54:39'),
(2,  1 ,'2015-05-09 12:56:39'),
(3, 10 ,'2015-05-09 12:56:39'),
(2,  5 ,'2015-05-09 13:48:30'),
(3, 16 ,'2015-05-09 13:48:30'),
(2,  7 ,'2015-05-09 15:01:09'),
(3, 20 ,'2015-05-09 15:01:09')


;WITH CTE AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [Time]) RN FROM @MyTable
)
SELECT T1.ID, T2.VAL - T1.VAL AS VALI, T2.Time FROM CTE T1
    INNER JOIN CTE T2 ON T1.ID = T2.ID AND T1.RN = T2.RN - 1
ORDER BY T1.[Time], T1.ID

结果:

ID          VALI        Time
----------- ----------- -----------------------
2           0           2015-05-09 12:56:39.000
3           0           2015-05-09 12:56:39.000
2           4           2015-05-09 13:48:30.000
3           6           2015-05-09 13:48:30.000
2           2           2015-05-09 15:01:09.000
3           4           2015-05-09 15:01:09.000

答案 1 :(得分:0)

您可以先按时间降序排序#tempTable,然后按ID分区。

然后您的加入成为:

select
    t1.Time,
    t1.[ID],
    t1.[VAL] - t2.[VAL] AS [ValI]
from #tempTable t1
inner join #tempTable t2 ON t1.[ID] = t2.[ID]
    AND t2.Rank = (t1.Rank + 1)

答案 2 :(得分:0)

这应该有效:

 select id, time, val-prevval val1 from (
 select * , lag(val, 1, 0) over(partition by  id order by val, time) prevVal from #Temp)A
 order by time

答案 3 :(得分:0)

如果您有LAG

<强> DEMO

   SELECT
        id
      , val - LAG(val, 1) OVER (PARTITION BY id ORDER BY time ASC) AS VALI
      , time
    FROM #TempTable
    ORDER BY time ASC, ID ASC

答案 4 :(得分:0)

LAG()在SQL 2012中可用。这使您可以获取当前行val并从上一行中减去val,按{{1}分组并按id排序。对于前两行,这将返回Time,因为他们没有先前的记录可供比较。您可以通过将查询置于子选择中然后应用NULL来排除它们,也可以使用WHERE valDiff IS NULL&gt;的第三个参数来默认valDiffLAG()将前两行默认为LAG(Val,1,0)

SQL Fiddle

MS SQL Server 2017架构设置

0

查询1

CREATE TABLE t1 ( ID int, VAL int, [Time] datetime) ;

INSERT INTO t1 ( ID, Val, [Time] )
VALUES 
    ( 2, 1 , '2015-05-09 12:54:39')
  , ( 3, 10, '2015-05-09 12:54:39')
  , ( 2, 1 , '2015-05-09 12:56:39')
  , ( 3, 10, '2015-05-09 12:56:39')
  , ( 2, 5 , '2015-05-09 13:48:30')
  , ( 3, 16, '2015-05-09 13:48:30')
  , ( 2, 7 , '2015-05-09 15:01:09')
  , ( 3, 20, '2015-05-09 15:01:09')
;

<强> Results

SELECT s1.ID
  , s1.ValDiff
  , FORMAT(s1.[Time], 'yyyy-MM-dd hh:mm:ss') AS fTime
FROM (
  SELECT ID
    , Val - LAG(Val,1) OVER ( PARTITION BY ID ORDER BY [Time],ID ) AS ValDiff
    , [Time]
  FROM t1
) s1
WHERE s1.valDiff IS NOT NULL
ORDER BY s1.[Time],s1.ID