根据下一条记录删除SQL中的记录

时间:2017-01-05 12:40:37

标签: sql sql-server tsql

我有列的记录:IDTime_EndAttribute

我需要删除所有记录,

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个数据库表,每个表中有数千条记录(当然还有更多列,我只提到那些对解决方案有影响的列)。记录从PLC发送到数据库,但有时(我们不知道原因)PLC也发送了错误的记录。

所以我需要的是一个查找错误记录并删除它们的查询。 :)

任何知道SQL代码应该如何的人?

3 个答案:

答案 0 :(得分:1)

请参阅下面的SQL。首先,我们使用两个窗口函数(LEAD)收集要删除的ID,以获取下一行所需的数据。然后,计算所有需要的数据,应用OP提出的评估规则。最后,使用获取的ID通过带有in子句的id删除平板电脑的受影响记录。

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

答案 1 :(得分: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;)。

答案 2 :(得分: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'
        );