【问题标题】:Extract Data by comparing 4 different rows通过比较 4 个不同的行来提取数据
【发布时间】:2020-01-09 09:37:47
【问题描述】:

Table数据如下,需要提取满足以下条件的记录

这里的值 = Value2-Value1

    Value of two days back data should be > 2
    Value of last day  data is < 0
    Value of next day data is < 4 and >0
    Value of after next day data > 4

所有日期都是工作日,如果任何日期在星期五,需要与第二天比较,即..星期一。并且仅与替代日期进行比较

必须从下面输出。

1         4-1-2018   15          18
2         3-1-2018    3           0 


    -----------------------------------
    code      Date      Value1      Value2
    ---------------------------------------
    1         1-1-2018   13          14
    1         2-1-2018   14          18
    1         3-1-2018   15          11
    1         4-1-2018   15          18
    1         5-1-2018   15          18
    1         6-1-2018   11          18
    1         7-1-2018   15          18
    2         1-1-2019    1           3
    2         2-1-2018    2           5
    2         3-1-2018    3           0
    2         4-1-2018    3           7
    2         5-1-2018    3           4
    2         6-1-2018    3           9
    2         7-1-2018    3           7

我在比较多行时非常困惑,非常感谢任何帮助。

【问题讨论】:

  • 请告诉我们实际的 RDBMS(可能是 SQL-Server)和版本。如果这是 SQL-Server 2012+,您可能会阅读 LEAD 和 LAG 以及 OVER 子句
  • 它的 sql server 2014

标签: sql-server tsql sql-server-2014


【解决方案1】:

从 v2012 开始,我们有 support for LAG() and LEAD()。试试这个:

SET DATEFORMAT dmy;

DECLARE @tbl TABLE(code INT,[Date] DATE,Value1 INT,Value2 INT);
INSERT INTO @tbl VALUES
 (1,'1-1-2018',13,14)
,(1,'2-1-2018',14,18)
,(1,'3-1-2018',15,11)
,(1,'4-1-2018',15,18)
,(1,'5-1-2018',15,18)
,(1,'6-1-2018',11,18)
,(1,'7-1-2018',15,18)
,(2,'1-1-2019', 1, 3)
,(2,'2-1-2018', 2, 5)
,(2,'3-1-2018', 3, 0)
,(2,'4-1-2018', 3, 7)
,(2,'5-1-2018', 3, 4)
,(2,'6-1-2018', 3, 9)
,(2,'7-1-2018', 3, 7);


WITH cte AS
(
    SELECT *
          ,LAG(Value2-Value1,2) OVER(PARTITION BY code ORDER BY [Date]) TwoDaysBack
          ,LAG(Value2-Value1,1) OVER(PARTITION BY code ORDER BY [Date]) Yesterday
          ,LEAD(Value2-Value1,1) OVER(PARTITION BY code ORDER BY [Date]) tomorrow
          ,LEAD(Value2-Value1,2) OVER(PARTITION BY code ORDER BY [Date]) TwoDaysAhead
    FROM @tbl 
)
SELECT *
FROM cte;

我不太明白,你想如何在过滤器中使用这些值来获得预期的输出。如果您需要这方面的帮助,请回来...

结果

+------+------------+--------+--------+-------------+-----------+----------+--------------+
| code | Date       | Value1 | Value2 | TwoDaysBack | Yesterday | tomorrow | TwoDaysAhead |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 1    | 2018-01-01 | 13     | 14     | NULL        | NULL      | 4        | -4           |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 1    | 2018-01-02 | 14     | 18     | NULL        | 1         | -4       | 3            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 1    | 2018-01-03 | 15     | 11     | 1           | 4         | 3        | 3            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 1    | 2018-01-04 | 15     | 18     | 4           | -4        | 3        | 7            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 1    | 2018-01-05 | 15     | 18     | -4          | 3         | 7        | 3            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 1    | 2018-01-06 | 11     | 18     | 3           | 3         | 3        | NULL         |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 1    | 2018-01-07 | 15     | 18     | 3           | 7         | NULL     | NULL         |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 2    | 2018-01-02 | 2      | 5      | NULL        | NULL      | -3       | 4            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 2    | 2018-01-03 | 3      | 0      | NULL        | 3         | 4        | 1            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 2    | 2018-01-04 | 3      | 7      | 3           | -3        | 1        | 6            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 2    | 2018-01-05 | 3      | 4      | -3          | 4         | 6        | 4            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 2    | 2018-01-06 | 3      | 9      | 4           | 1         | 4        | 2            |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 2    | 2018-01-07 | 3      | 7      | 1           | 6         | 2        | NULL         |
+------+------------+--------+--------+-------------+-----------+----------+--------------+
| 2    | 2019-01-01 | 1      | 3      | 6           | 4         | NULL     | NULL         |
+------+------------+--------+--------+-------------+-----------+----------+--------------+

简而言之:

LAG() 和 LEAD() 都采用所需值的参数,第二个参数是我们要跳过的行数,第三个参数是您可以指定的默认值,以避免结果中出现 NULL。范围内没有行。

OVER() 子句将告诉任何 windowing 函数,如果我们想将集合视为分组和排序顺序(否则系统将不知道什么是 leading 或滞后

【讨论】:

    【解决方案2】:

    使用leadlag 窗口函数:

    with cte as (
      select *,
        lag(value2 - value1, 2) over (partition by code order by date) prev2,
        lag(value2 - value1, 1) over (partition by code order by date) prev1,
        lead(value2 - value1, 1) over (partition by code order by date) next1,
        lead(value2 - value1, 2) over (partition by code order by date) next2
      from tablename
    )
    select code, date, value1, value2
    from cte 
    where prev2 > 2 and prev1 < 0 and next1 > 0 and next1 < 4 and next2 > 4
    

    请参阅demo
    结果:

    code | date                | value1 | value2
    ---: | :------------------ | -----: | -----:
       1 | 01/04/2018 00:00:00 |     15 |     18
       2 | 01/04/2018 00:00:00 |      3 |      7
    

    您对code = 2 的预期结果与我的结果之间存在差异,因此请检查其有效性。

    【讨论】:

    • Nice forpas,我需要做一个作为答案,所以 Shnugo 首先回答,但你的输出是我需要如此赞成的输出.. 感谢 forpas 和 Shnugo 的帮助......我正在尝试解决方案很快就会回复您。
    猜你喜欢
    • 2018-08-24
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2020-04-11
    • 2019-06-06
    • 2022-01-02
    • 1970-01-01
    • 2022-07-08
    相关资源
    最近更新 更多