【问题标题】:Condition on window-functions (SQL)窗口函数的条件 (SQL)
【发布时间】:2022-01-12 10:25:35
【问题描述】:

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

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

我可以通过写作得到这张表:

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 (as C92320->F45910) 或 1254 (as F45910->J20920) 感兴趣。所以我想要的表看起来像:

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

有没有办法做到这一点?

【问题讨论】:

标签: sql-server window-functions


【解决方案1】:

正如@Larnu 指出的,您需要PARTITION BYCASE 表达式来检查负数。

试试这个:

-- 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

【讨论】:

  • 谢谢!另一个问题:得到这个表后,如何只选择那些差异大于某个阈值的行?
  • &lt; 0 替换为您要查找的阈值。
  • 是的!但是如何过滤掉所有带有 NULL 的行?
  • 我想丢弃 diff 中所有包含 NULL 的行,只保留大于阈值的行。所以在我用我的阈值替换
  • 我已经更新了我的答案。只需使用WHERE 条件。
猜你喜欢
  • 2016-02-11
  • 1970-01-01
  • 2017-07-15
  • 1970-01-01
  • 2018-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多