整蛊删除。我如何能?

时间:2010-11-16 16:42:20

标签: sql sql-delete

我有一个包含2列(两个INT)的表,并且有40万条记录(很多)。 第一列是按ASC排序的随机数。第二列有一个规则(现在不重要) 在表中有1000条记录,这是例外。因此,而不是“规则”,只有“-1”值的单元格。

如何删除〜399 000条记录,所以我希望在我的表格中只留下-1和它们的“邻居”(-1之前和之后的记录)

UPDATE sql server 2k5 第一列值 - 是唯一的,但不是ID-s(它不是​​++:D)

示例:

之前:

 20022518   13
 20022882   364
 20022885   -1
 20022887   5
 20022905   18
 20023200   295
 20023412   212
 20023696   284
 20024112   416
 20025015   903
 20025400   385
 20025401   -1
 20025683   283
 20025981   298
 20025989   8
 20026752   763
 20027779   1027
 20028344   565
 20028350   6
 20028896   546
 20028921   25
 20028924   -1
 20028998   77
 20029031   33
 20029051   20
 20029492   441
 20029530   38
 20029890   360

后:

 20022882   364
 20022885   -1
 20022887   5
 20025400   385
 20025401   -1
 20025683   283
 20028921   25
 20028924   -1
 20028998   77

4 个答案:

答案 0 :(得分:2)

在这里假设SQL Server。如果您要保留一个非常小的数据集,最好的选择是插入新表。即:

SELECT *
INTO MyTable2
FROM MyTable
WHERE ColumnB = -1

DROP TABLE MyTable

exec sp_rename MyTable2 MyTable

这将是一个记录最少的操作,将在DELETE的一小部分时间内运行。

没有其他密钥,就无法确保获得“邻居”,因为这在关系数据库中并不是真正有效的概念。如果第一列是“随机”,则无法分辨哪些是“之前”和“之后”一行的值为-1。

如果通过“随机”表示它就像IDENTITY列自动增加,并且您在序列中没有任何缺失值,您可以执行以下操作:

SELECT *
INTO MyTable2
FROM MyTable mt
WHERE ColumnB = -1
OR WHERE EXISTS (
     SELECT * FROM MyTable mt2
     WHERE mt2.id = mt.id + 1
     OR mt2.id = mt.id -1)

DROP TABLE MyTable

exec sp_rename MyTable2 MyTable

答案 1 :(得分:2)

如果我理解正确,您希望将所有记录保留为col2 = -1,将记录中最接近col1的记录保存为-1。假设在col1中没有重复,我会做这样的事情

delete from table where not col1 in 
(
    (select col1 from table where col2 = -1)
union
    (select (select max(t2.col1) from table t2 where t2.col1 < t1.col1) from table t1 where t1.col2 = -1)
union
    (select (select min(t4.col1) from table t4 where t4.col1 > t3.col1) from table t3 where t3.col2 = -1)
)

修改
t4.col1 < t3.col1应为t4.col1 > t3.col1 我创建了一个带有col1和col2的测试表,两者都是int,col1是PK,但不是autonumber

SELECT * from adjacent

给出

col1    col2
1   5
3   4
4   2
7   -1
11  8
12  2

使用以上子选择:

SELECT * from adjacent
where
col1 in 
(
    (select col1 from adjacent where col2 = -1)
union
    (select (select max(t2.col1) from adjacent t2 where t2.col1 < t1.col1) from adjacent t1 where t1.col2 = -1)
union
    (select (select min(t4.col1) from adjacent t4 where t4.col1 > t3.col1) from adjacent t3 where t3.col2 = -1)
)

给出

col1    col2
4   2
7   -1
11  8

not

SELECT * from adjacent
where
col1 not in 
(
    (select col1 from adjacent where col2 = -1)
union
    (select (select max(t2.col1) from adjacent t2 where t2.col1 < t1.col1) from adjacent t1 where t1.col2 = -1)
union
    (select (select min(t4.col1) from adjacent t4 where t4.col1 > t3.col1) from adjacent t3 where t3.col2 = -1)
)

给出

col1    col2
1   5
3   4
12  2

最后删除并选择

delete from adjacent
where
col1 not in 
(
    (select col1 from adjacent where col2 = -1)
union
    (select (select max(t2.col1) from adjacent t2 where t2.col1 < t1.col1) from adjacent t1 where t1.col2 = -1)
union
    (select (select min(t4.col1) from adjacent t4 where t4.col1 > t3.col1) from adjacent t3 where t3.col2 = -1)
)

select * from adjacent

给出

col1    col2
4   2
7   -1
11  8

答案 2 :(得分:0)

解决方案是首先对记录进行编号,识别与-1规则相邻的记录,然后使用UNION汇总最终结果:

WITH Numbered(seq, id, ruleno) AS (
 SELECT
  ROW_NUMBER() OVER (ORDER BY id), id, ruleno
 FROM
  Tricky
),
Brothers(id, ruleno) AS (
 SELECT
  b.id, b.ruleno
 FROM
  Numbered a INNER JOIN Numbered b
  ON a.ruleno = -1 AND
  abs(a.seq - b.seq) = 1
),
Triplets(id, ruleno) AS (
 SELECT
  id, ruleno
 FROM
  Tricky
 WHERE
  ruleno = -1
 UNION ALL
 SELECT
  id, ruleno
 FROM
  Brothers
)
-- Display results
SELECT 
 id, ruleno
FROM
 Triplets
ORDER BY
 id

结果:

id ruleno
20022882 364
20022885 -1
20022887 5
20025400 385
20025401 -1
20025683 283
20028921 25
20028924 -1
20028998 77

最后:

DELETE FROM
  Tricky
WHERE
  id NOT IN (
    SELECT 
      id
    FROM
      triplets
  )

答案 3 :(得分:0)

使用这个棘手的问题:

为此,我通过以下语句创建了一个表: create table t1(val int,val2 int) GO

- 下面是确切的stmt:

用CTE作为(选择val,val2,row_number()over(由val ASC命令)作为rnum 来自t1) 删除t1 从t1内部加入cte a ON t1.val = a.val INNER JOIN(SELECT * fROM cte,其中val2 = -1)为b 在a.rnum = b.rnum 或者a.rnum = b.rnum - 1 或者a.rnum = b.rnum + 1

有关更多信息,请参阅此帖子: http://blog.sqlauthority.com/2009/08/08/sql-server-multiple-cte-in-one-select-statement-query/