在SQL中查询产品历史记录

时间:2019-12-26 11:06:32

标签: sql sql-server tsql

我是SQL新手。我有一张有几列的桌子。其中一个填充了产品的实际序列号,另一个填充了先前的序列号。

我需要一个查询,给定实际的序列号或产品名称,它将返回更改历史记录。

示例:

ProdName   Actual SN   Prev SN    
------------------------------
P1           681         300    
P2           123         123    
P3           555         123    
P4           777         555    
P5           999         999    
P6           666         888    
P7           333         111    
P8           987         777

我需要了解产品历史记录。例如, P8 历史记录为:

ProdName    SN    
----------------
P8          987    
P4          777    
P3          555    
P2          123

(当“ Actual SN” ==“ Prev SN”时应停止)

谢谢!

3 个答案:

答案 0 :(得分:2)

这可以通过使用在父/子对之间循环的递归CTE来解决。

WITH RCTE_PRODUCT_HISTORY AS
(
    -- seeding the recursive
    SELECT ProdName, [Actual SN], [Prev SN]
    , [Actual SN] AS StartSN
    , 0 AS Lvl
    FROM YourProductHistoryTable
    WHERE ProdName = 'P8'

    UNION ALL

    -- looping the recursive till nothing new is found, or condition is met
    SELECT t.ProdName, t.[Actual SN], t.[Prev SN]
    , c.StartSN
    , c.Lvl + 1
    FROM RCTE_PRODUCT_HISTORY c
    JOIN YourProductHistoryTable t
      ON t.[Actual SN] = c.[Prev SN]
    WHERE t.[Prev SN] != c.StartSN
      AND t.[Actual SN] != c.[Actual SN]
)
SELECT ProdName, [Actual SN] AS SN
FROM RCTE_PRODUCT_HISTORY
ORDER BY Lvl

db <>小提琴enter image description here

的测试

答案 1 :(得分:0)

您可以使用递归:

with cte as (
    select ProdName, ActualSN, PrevSN, 0 lvl from mytable where ProdName = 'P8'
    union all
    select t.ProdName, t.ActualSN, t.prevSN, lvl + 1
    from mytable t
    inner join cte c on c.PrevSN = t.ActualSN and c.PrevSN != c.ActualSN
)
select ProdName, ActualSN SN from cte order by lvl

Demo on DB Fiddle

ProdName | SN 
:------- | :--
P8       | 987
P4       | 777
P3       | 555
P2       | 123

答案 2 :(得分:0)

您可以尝试以下查询。

WITH cte_Product([Productname], [ActualSN],[PreviousSN],RN) 
AS (
    SELECT * ,0 as RN
    From [dbo].[SN]
    where [Productname]='p8'
    UNION ALL
    SELECT  s.*,RN+1 from [dbo].[SN] s
    INNER JOIN  cte_Product cn on s.ActualSN=cn.[PreviousSN]
    and cn.ActualSN !=cn.[PreviousSN]    
)
SELECT 
    *
FROM 
    cte_Product