2017-01-05 5 views
0

У меня есть записи с колонками: ID, Time_End и Attribute.Удаление записи в SQL в зависимости от следующей записи

Мне нужно удалить все записи,

WHERE Time_End = '1990-01-01 00:00:00.000' AND Attribute <> '9' 

но только:

  • , если следующая строка не имеет тот же номер атрибута

или

  • следующая строка имеет тот же номер атрибута и значение Time_End из 1990-01-01 00:00:00.000

Например:

ID  Time_End      Attribute 
--------------------------------------------- 
235 1990-01-01 00:00:00.000  5     /delete 
236 1990-01-01 00:00:00.000  5     /delete 
237 1990-01-01 00:00:00.000  5 
238 2016-10-10 23:45:40.000  5 


ID  Time_End      Attribute 
--------------------------------------------- 
312 1990-01-01 00:00:00.000  8     /delete 
313 2016-01-09 18:00:00.000  6     
314 1990-01-01 00:00:00.000  4     /delete 
315 1990-01-01 00:00:00.000  7 
316 2016-10-10 23:45:40.000  7 

Наш клиент имеет 50 таблиц базы данных с тысячами записей в каждой таблице (и, конечно, больше столбцы, я упомянул только те, которые оказывают влияние на решение). Записи отправляются в базу данных с ПЛК, но иногда (мы не знаем, почему) ПЛК посылает также неверные записи.

Так что мне нужен запрос, который находит эти неправильные записи и удаляет их. :)

Любой, кто знает, как должен выглядеть код SQL?

+0

Я удалил несовместимые теги базы данных. Пожалуйста, пометьте базу данных, которую вы фактически используете. –

+0

Используете ли вы сервер MS SQL – DhruvJoshi

+0

Да, я использую MS SQL –

ответ

1

См. Мой SQL ниже. Во-первых, мы собираем идентификаторы для удаления, используя две функции окна (LEAD), чтобы получить следующую необходимую строку. Затем, используя все необходимые данные, примените правила оценки, предложенные OP. Наконец, используйте полученные идентификаторы для удаления затронутых записей планшета по id с помощью предложения in.

DELETE toDeleteTable 
WHERE toDeleteTable.id IN (WITH dataSet 
           AS (SELECT toDeleteTable.id, 
             toDeleteTable.time_end, 
             toDeleteTable.attribute, 
             LEAD(toDeleteTable.time_end,1,0) OVER (ORDER BY toDeleteTable.id) AS next_time_end, 
             LEAD(toDeleteTable.attribute,1,0) OVER (ORDER BY toDeleteTable.id) AS next_attribute 
            FROM toDeleteTable) 
          SELECT dataSet.id 
           FROM dataSet 
          WHERE dataSet.time_end = '1990-01-01 00:00:00.000' 
           AND dataSet.attribute <> '9' 
           AND ( (dataSet.next_attribute = dataSet.attribute AND dataSet.next_time_end = '1990-01-01 00:00:00.000') 
            OR dataSet.next_attribute <> dataSet.attribute) 
          ) 
+0

Спасибо за ваш ответ.Чтобы убедиться, что это так полезно, добавьте некоторое объяснение, чтобы показать, как вы решили проблему OP. – Tom

+0

Сначала собирайте идентификаторы для удаления, используя две функции окна (LEAD), чтобы получить следующую необходимую строку. Затем, используя все необходимые данные, примените правила оценки, предложенные OP. Наконец, используйте полученные идентификаторы для удаления затронутых записей планшета по id с помощью предложения in. – cmoron

+0

Спасибо! Это то, что я искал :) –

0

Я думаю, что вы можете использовать ROW_NUMBER() так:

;WITH t AS (
    SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY Time_End ORDER BY ID DESC) AS seq 
    FROM yourTable 
    WHERE Attribute <> '9' 
     AND Time_End = CAST('1990-01-01 00:00:00.000' as datetime) 
) 
DELETE FROM t 
WHERE seq > 1; 

Не испытано - HTH;).

+0

Это не учитывает полный набор требований к тому, что нужно удалить: «если запись в следующей строке имеет не тот же номер атрибута или запись в следующей строке, имеет тот же номер атрибута и Time_End = '1990-01-01 00:00: 00.000'_ " – iamdave

+0

Точно, он удаляет больше записей, чем должен :) –

0

Вы можете выполнить это с помощью простого соединения apply. Нижеследующее должно дать вам достаточно, чтобы выполнить эту работу без каких-либо сложных задач:

declare @t table(ID int 
       ,Time_End datetime 
       ,Attribute int 
       ); 
insert into @t values(235,'1990-01-01 00:00:00.000',5),(236,'1990-01-01 00:00:00.000',5),(237,'1990-01-01 00:00:00.000',5),(238,'2016-10-10 23:45:40.000',5),(312,'1990-01-01 00:00:00.000',8),(313,'2016-01-09 18:00:00.000',6),(314,'1990-01-01 00:00:00.000',4),(315,'1990-01-01 00:00:00.000',7),(316,'2016-10-10 23:45:40.000',7); 

select t.* 
     ,tm.* 
from @t t 
    outer apply (select top 1 tt.Time_End 
          ,tt.Attribute 
        from @t tt 
        where t.ID < tt.ID 
        order by tt.ID 
        ) tm 
where t.Attribute <> tm.Attribute 
    or (t.Attribute = tm.Attribute 
     and tm.Time_End = '1990-01-01 00:00:00.000' 
     ); 
Смежные вопросы