window-函数条件 (SQL)

Condition on window-functions (SQL)

我有一个 table 是我将几个 table 连接在一起后得到的,它看起来像这样:

SELECT TOP(200)
A.Value as value,readDate,symbol,description,VIN
FROM Table1 as V
JOIN Table2 ON Table2.VX_Id=V.VX_Id
JOIN Table3 ON Table3.FX_Id =Table2.FX_Id
JOIN Table4 on Table3.FX_Id=Table4.FX_Id
JOIN Table5 as A on A.RX_Id=Table4.RX_Id
WHERE symbol='SV'
ORDER BY VIN,readDate


value   readDate                symbol   description      VIN  
------   ---------------------   -----    ----------      ------               
105     2013-02-05 15:17:25.000     SV     text1          C92320
120     2013-02-05 15:25:25.000     SV     text2          C92320
234     2013-01-22 06:17:55.000     SV     text3          F45910   
240     2013-01-23 07:20:55.000     SV     text4          F45910
246     2013-01-23 09:20:55.000     SV     text5          F45910
1500    2015-10-24 12:48:38.000     SV     text6          J20920   
337     2014-01-24 11:58:38.000     SV     text7          P20824 

我想计算下一个值和上一个值的差值(具有此差值的新列):

value    difference      readDate                symbol   description      VIN  
------    ----           ---------------------   -----    ----------      ------               
105       NULL          2013-02-05 15:17:25.000     SV     text1          C92320
120       15            2013-02-05 15:25:25.000     SV     text2          C92320
234       114           2013-01-22 06:17:55.000     SV     text3          F45910   
240       6             2013-01-23 07:20:55.000     SV     text4          F45910
246       6             2013-01-23 09:20:55.000     SV     text5          F45910
1500      1254          2015-10-24 12:48:38.000     SV     text6          J20920   
337       -1163         2014-01-24 11:58:38.000     SV     text7          P20824

我可以通过以下方式得到这个table:

SELECT TOP(200)
A.Value as value,A.Value-LAG(A.Value, 1) OVER (ORDER BY VIN,readDate) as 
difference,readDate,symbol,description,VIN
FROM Table1 as V
JOIN Table2 ON Table2.VX_Id=V.VX_Id
JOIN Table3 ON Table3.FX_Id =Table2.FX_Id
JOIN Table4 on Table3.FX_Id=Table4.FX_Id
JOIN Table5 as A on A.RX_Id=Table4.RX_Id
WHERE symbol='SV'

我只对来自相同 VIN 号码的正数差异感兴趣,因此我对 114(如 C92320->F45910)或 1254(如 F45910->J20920)不感兴趣。所以我想要的 table 看起来像:

value    difference      readDate                symbol   description      VIN  
------    ----           ---------------------   -----    ----------      ------               
105       NULL          2013-02-05 15:17:25.000     SV     text1          C92320
120       15            2013-02-05 15:25:25.000     SV     text2          C92320
234       NULL          2013-01-22 06:17:55.000     SV     text3          F45910   
240       6             2013-01-23 07:20:55.000     SV     text4          F45910
246       6             2013-01-23 09:20:55.000     SV     text5          F45910
1500      NULL          2015-10-24 12:48:38.000     SV     text6          J20920   
337       NULL         2014-01-24 11:58:38.000      SV     text7          P20824

有办法吗?

正如@Larnu 指出的那样,您需要 PARTITION BY 和一个 CASE 表达式来检查负数。

试试这个:

-- To check for negative numbers we need another select in order to be able to use the result calculated by LAG
SELECT TOP(200) [value], ( CASE WHEN difference < 0 THEN NULL ELSE difference END ) AS difference, readDate, symbol, description, VIN
FROM
    ( SELECT 
    -- Added PARTITION BY
    A.Value as value,A.Value-LAG(A.Value, 1) OVER (PARTITION BY VIN ORDER BY readDate) as 
    difference, readDate, symbol, description, VIN
    FROM Table1 as V
    JOIN Table2 ON Table2.VX_Id=V.VX_Id
    JOIN Table3 ON Table3.FX_Id =Table2.FX_Id
    JOIN Table4 on Table3.FX_Id=Table4.FX_Id
    JOIN Table5 as A on A.RX_Id=Table4.RX_Id
    WHERE symbol='SV' ) AS MainQuery
-- Optionally you can exclude records where difference is 0 or less
WHERE difference > 0
ORDER BY VIN,readDate

奖励问题的答案

要删除重复的 VIN,您可以尝试以下方法:

SELECT *
FROM(
    -- To check for negative numbers we need another select in order to be able to use the result calculated by LAG
    SELECT TOP(200) [value], ( CASE WHEN difference < 0 THEN NULL ELSE difference END ) AS difference,
        -- Order differences per VIN in descending order. Note: 1 - is the largest difference; numbering will restart from 1 for each VIN
        ROW_NUMBER() OVER( PARTITION BY VIN ORDER BY difference DESC ) AS DifferenceRank,
        readDate, symbol, description, VIN
    FROM
        ( SELECT 
        -- Added PARTITION BY
        A.Value as value,A.Value-LAG(A.Value, 1) OVER (PARTITION BY VIN ORDER BY readDate) as 
        difference, readDate, symbol, description, VIN
        FROM Table1 as V
        JOIN Table2 ON Table2.VX_Id=V.VX_Id
        JOIN Table3 ON Table3.FX_Id =Table2.FX_Id
        JOIN Table4 on Table3.FX_Id=Table4.FX_Id
        JOIN Table5 as A on A.RX_Id=Table4.RX_Id
        WHERE symbol='SV' ) AS MainQuery
    -- Optionally you can exclude records where difference is 0 or less
    WHERE difference > 0
    ORDER BY VIN, readDate ) AS DifferenceFilter
-- We only want the biggest difference
WHERE DifferenceRank = 1