在合格的行之后删除第一行

时间:2015-03-26 15:18:56

标签: sql sql-server tsql

我们假设我有下表名为订单

---------------------------------
| OrderId | Status | CustomerId |
---------------------------------
|    1    |   +    |      2     |
---------------------------------
|    2    |   -    |      1     |
---------------------------------
|    3    |   +    |      2     |
---------------------------------
|    4    |   +    |      1     |
---------------------------------
|    5    |   -    |      3     |
---------------------------------
|    6    |   +    |      4     |
---------------------------------
|    7    |   +    |      3     |
---------------------------------

问题是如何在每个客户取消一个订单后删除下一个订单?我基本上想删除id = 4,7的订单。 所以结果应该是:

---------------------------------
| OrderId | Status | CustomerId |
---------------------------------
|    1    |   +    |      2     |
---------------------------------
|    2    |   -    |      1     |
---------------------------------
|    3    |   +    |      2     |
---------------------------------
|    5    |   -    |      3     |
---------------------------------
|    6    |   +    |      4     |
---------------------------------

我使用SQL Server,但我真的很好奇使用ANSI SQL编写它。

1 个答案:

答案 0 :(得分:1)

您可以获得每位客户的最后取消订单。然后删除订单:

with todelete as (
      select t.*,
             min(case when status = '-' then orderid end) over
                 (partition by customerid) as deleted_orderid
      from table t
     )
delete from todelete
    where orderid > deleted_orderid;

编辑:

要仅删除下一个,请使用row_number()

with todelete as (
      select t.*, min(case when orderid > deleted_orderid then orderid end) over
                      (partition by customerid) as orderid_to_delete
      from (select t.*,
                   min(case when status = '-' then orderid end) over
                       (partition by customerid) as deleted_orderid
            from table t
           ) t
     )
delete from todelete
    where orderid = orderid_to_delete;

编辑II:

如果要在任何删除后删除下一个订单,查询会更简单:

with todelete as (
      select t.*, lag(status) over (partition by customerid order by orderid) as prev_status
      from table t
     )
delete from todelete
    where prev_status = '-';

这是ANSI SQL。如果您使用的是SQL Server 2008,则需要使用相关的子查询或cross apply(我并非100%确定cross apply将在删除CTE中起作用,但它应该。)