【问题标题】:How can I retrieve previous and next rows by certain condition如何按特定条件检索上一行和下一行
【发布时间】:2022-11-30 23:53:58
【问题描述】:

我的目标只是检索每个昵称和同一日期的总负值之前的行。

桌子 :

enter image description here

我不想检索 orderid 8 和 orderid9,因为相同昵称和同一天的上述行包含负总值。出于同样的原因,我不想检索 orderid 为 7 的行。我不想检索 orderid 5 和 orderid 6,因为它们包含负总值。我的目标是检索 orderid10,尽管同一昵称的上述行包含负值,因为日期已更改。

预期结果:enter image description here

我试图解决 using with 子句和子查询的问题,但我失败了。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    欢迎来到堆栈溢出。

    当您提出这样的问题时,提供 DDL 和 DML 以正确解释您的问题真的很有帮助。请不要为此使用图片,因为它们不容易复制和粘贴。提供演示数据的一个好方法是:

    DECLARE @table TABLE (RowID INT IDENTITY, Value INT, Name NVARCHAR(10))
    INSERT INTO @table (Value, Name) VALUES
    (1, 'E'),(2, 'D'),(3, 'C'),(4, 'B'),(5, 'A'),
    (1, 'V'),(2, 'W'),(3, 'X'),(4, 'Y'),(5, 'Z'),
    (1, 'M'),(2, 'N'),(3, 'O'),(4, 'P'),(5, 'Q')
    

    关于你的问题。

    听起来您正在寻找的是 LAG 和 LEAD 窗口函数。窗口函数在您定义的窗口上运行:

    SELECT *, LAG(Name,1) OVER (PARTITION BY Value ORDER BY RowID) AS PreviousName, LEAD(Name,1) OVER (PARTITION BY Value ORDER BY RowID) AS NextName
      FROM @table
    

    这些函数采用您想要的列名,以及要移动的行数(LAG 向后移动,LEAD 向前移动)。在 OVER 中我们使用 PARTITION 和 ORDER BY 来定义窗口。 PARTITION 基本上将事物组合在一起,ORDER BY 确定该组中的顺序。如果移至的行不存在(没有上一行或下一行),则返回 NULL。

    RowID   Value   Name    PreviousName    NextName
    ------------------------------------------------
    1       1       E       NULL            V
    6       1       V       E               M
    11      1       M       V               NULL
    2       2       D       NULL            W
    7       2       W       D               N
    12      2       N       W               NULL
    3       3       C       NULL            X
    8       3       X       C               O
    13      3       O       X               NULL
    4       4       B       NULL            Y
    9       4       Y       B               P
    14      4       P       Y               NULL
    5       5       A       NULL            Z
    10      5       Z       A               Q
    15      5       Q       Z               NULL
    

    如果您可以提供一些更好的示例数据,我也可以回答您问题的其他要点。

    【讨论】:

      【解决方案2】:

      我知道您不希望包含具有相同昵称和日期的总计为负值的行。使用NOT EXISTS

      SELECT t.*
      FROM TableName t
      WHERE NOT EXISTS
      (
          SELECT 1 FROM TableName t2
          WHERE t1.Nickname = t2.Nickname 
            AND CAST(t1.Date as date) = CAST(t2.Date as date)
            AND t2.Total < 0
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 2022-11-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-13
        • 1970-01-01
        相关资源
        最近更新 更多