在ID级别显示最早的值和最新的值

时间:2019-04-25 21:22:42

标签: sql sql-server tsql

我有一张看起来像这样的表,其中以旧值和新值(刚变成的值)显示id。

IF OBJECT_ID('tempdb.dbo.#TT','U')IS NOT NULL
    DROP TABLE #TT;

SELECT *
INTO #TT
FROM (
SELECT 1 AS ID, 'A' AS OldValue, 'B' AS NewValue, CONVERT(DATE,'20190421') AS [Date]
UNION ALL
SELECT 1 AS ID, 'B' AS OldValue, 'C' AS NewValue, CONVERT(DATE,'20190423') AS [Date]
UNION ALL
SELECT 2 AS ID, 'D' AS OldValue, 'E' AS NewValue, CONVERT(DATE,'20190422') AS [Date]
UNION ALL
SELECT 3 AS ID, 'J' AS OldValue, 'K' AS NewValue, CONVERT(DATE,'20190422') AS [Date]
UNION ALL
SELECT 3 AS ID, 'K' AS OldValue, 'L' AS NewValue, CONVERT(DATE,'20190423') AS [Date]
UNION ALL
SELECT 3 AS ID, 'L' AS OldValue, 'M' AS NewValue, CONVERT(DATE,'20190424') AS [Date]
) T
;

我想显示每个id和旧值以及最新的值。例如ID = 1和OldValue = A应该显示C或ID = 3并且OldValue = K应该显示M

我试图按如下方式进行递归cte:

WITH RecCTE AS (
SELECT ID, OldValue, NewValue
FROM #TT
UNION ALL
SELECT A.ID, B.OldValue, A.NewValue
FROM #TT A
INNER JOIN RecCTE B ON A.ID = B.ID AND B.NewValue = A.OldValue
)

SELECT *
FROM RecCTE

使用该递归查询。我正确地获得了一些线条,但中间也得到了额外的线条:

|       ID  |   OldValue    |    NewValue    |
|-----------|---------------|----------------|
|       1   |      A        |       B        |
|       1   |      B        |       C        |
|       2   |      D        |       E        |
|       3   |      J        |       K        |
|       3   |      K        |       L        |
|       3   |      L        |       M        |
|       3   |      K        |       M        |
|       3   |      J        |       L        |
|       3   |      J        |       M        |
|       1   |      A        |       C        |

我想要这样的结果:

    |       ID  |   OldValue    |    NewValue    |
    |-----------|---------------|----------------|
    |       1   |      A        |       C        |
    |       1   |      B        |       C        |
    |       2   |      D        |       E        |
    |       3   |      J        |       M        |
    |       3   |      K        |       M        |
    |       3   |      L        |       M        |

2 个答案:

答案 0 :(得分:0)

我认为走最后一行应该可以:

WITH RecCTE AS (
      SELECT ID, OldValue, NewValue, 1 as lev
      FROM #TT
      UNION ALL
      SELECT A.ID, B.OldValue, A.NewValue, lev + 1
      FROM #TT A JOIN
           RecCTE B
           ON A.ID = B.ID AND B.NewValue = A.OldValue
     )
SELECT *
FROM (SELECT r.*, ROW_NUMBER() OVER (PARTITION BY id, OldValue ORDER BY lev DESC) as seqnum
      FROM RecCTE r
     ) r
WHERE seqnum = 1;

答案 1 :(得分:0)

如果数据按我认为的方式工作,那么下面的代码将不使用递归进行操作:

auto1