2015-03-26 5 views
-2

Давайте предположим, что я следующая таблица называется Заказы:Удалить первые строки после квалифицированных те

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

+0

Это можно сделать довольно легко, используя окно но более старые версии sql-сервера не поддерживают их. Какую версию sql-сервера вы используете? Если он старше, то, скорее всего, и трюк тоже сделает совпадение 'ON orderid = orderid-1'. – JNevill

+0

@JNevill, SQL Server 2005 –

ответ

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; 

EDIT:

Чтобы удалить только следующий, давайте использовать 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; 

EDIT II:

Если вы хотите удалить следующий заказ после любой delete, запрос немного проще:

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, но он должен.)

+0

Мне нужно удалить только один заказ после отмены. Кажется, что этот код удаляет все из них, верно? –

+0

Я пересмотрю ответ, но в вашем вопросе четко сказано: «Как я могу удалить следующие заказы после отмены одного для каждого клиента». Обратите внимание на «следующие заказы ... для каждого клиента. –

+0

Я верю, что вы должны удалить функцию min() из вложенного выбора, не так ли? –

Смежные вопросы