TSQL - 计算从昨天到今天的值之间的差异,SELF JOIN 问题

TSQL - Calculate difference between values from yesterday to today, SELF JOIN question

我已经将各种在线答案的代码拼凑在一起以获得我想要的结果,但是,我不明白它为什么起作用,我想知道 JOIN 在它说 RowNum + 1 的地方实际上做了什么。

原题是计算一个值从昨天到今天的百分比差。我对自我加入有点模糊,但我确实理解自我加入。当我添加 RowNum 列时,这让我很困惑。


问题

请问 T2.RowNum = T1.RowNum + 1 在自连接中做什么?

IF OBJECT_ID('tempdb..#t1') IS NOT NULL DROP TABLE #t1

CREATE TABLE #T1 (
ProductTotal int
,CountDate date
)

INSERT INTO #t1
VALUES 
       (893911,'20200815')
      ,(888970,'20200816')
      ,(899999,'20200817')
      

WITH cte AS (
SELECT 
 ROW_NUMBER() OVER(ORDER BY CountDate) AS RowNum
,ProductTotal
,CountDate
FROM #t1
WHERE   CountDate > CAST(GETDATE () - 2 AS DATE)
)
SELECT 
    t1.RowNum
   ,t1.ProductTotal   
   ,CAST(((t1.ProductTotal - t2.ProductTotal) * 1.0 / t2.ProductTotal) * 100 AS DECIMAL(10,2))  AS ProductDiff
   ,t1.CountDate
FROM cte AS t1
LEFT JOIN cte t2 ON T2.RowNum = T1.RowNum + 1

假设您每天都有值,更好的方法是使用 lag():

SELECT ProductTotal, CountDate,
       (ProductTotal - prev_ProductTotal) * 1.0 / ProductTotal
FROM (SELECT t.*, 
             LAG(ProductTotal) OVER (ORDER BY CountDate) as prev_ProductTotal
      FROM #t1 t
     ) t
WHERE CountDate > CAST(GETDATE () - 1 AS DATE)

请注意,正如我评论的那样,我完全同意 Gordon 的观点,LAG(或 LEAD)是这里的正确答案。解释你在评论中提出的问题 “我不明白 T2.RowNum = T1.RowNum + 1 是如何工作的”:

JOIN returns 行,其中 ON 中的表达式为真。由于您有 INNER JOIN,因此仅显示 JOIN 两侧的表达式计算结果为 True 的行。对于 LEFT JOIN 之前返回的任何先前内容都不会“丢失”。 (还有其他类型的联接。)

对于T2.RowNum = T1.RowNum + 1,这是基础数学。 2 匹配到 1 (1+1),3 匹配到 2 (2+1)... 100 是匹配到 99 (99 + 1)。因此,根据 CTE 中定义的 ROW_NUMBER 顺序,来自 T1 的数据与“之后”的行相匹配。在这种情况下,这将是 CountDate 的“下一个”值按升序排列的行。