我想根据两列的组合删除行。我的表看起来像这样(简化):
[ID], [Sub_ID], [Value]
值可以是:
1234 - 1 - 100
1234 - 2 - 50
5678 - 1 - 90
4321 - 1 - 75
4321 - 2 - 75
我想删除除[ID]和[Sub_ID]的某些特定组合之外的所有记录。示例:删除除组合1234-2和4321-2之外的所有组合。
*编辑:这两个值是一个例子,实际上我需要保持超过10,000个ID-Sub_ID组合。
为此,我将两个ID列与强制转换组合在一起,并删除与此组合不匹配的所有内容。
Delete
from table
where
CAST(ID as varchar(4))+'-'+Cast(Sub_ID as varchar(1)) not in
('1234-2', '4321-2')
这有效,但速度很慢,可能非常低效。执行此查询已经花费了几分钟,我将每个月扩展选择,可能每次都更糟糕,有谁知道我如何才能提高效率?
非常感谢, 史蒂芬
答案 0 :(得分:0)
您可以使用CTE
选择所有不应删除的记录,然后您可以将其与原始表一起加入:
WITH Keep AS
(
SELECT ID=1234, Sub_ID=2
UNION ALL
SELECT ID=4321, Sub_ID=2
)
SELECT t.*
FROM Table1 t INNER JOIN Keep k
ON t.ID = k.ID AND t.Sub_ID = k.Sub_ID
这显示了您要保留的内容:demo
如果您想删除另一个,可以使用NOT EXISTS
:
WITH Keep AS
(
SELECT ID=1234, Sub_ID=2
UNION ALL
SELECT ID=4321, Sub_ID=2
)
DELETE t FROM Table1 t WHERE NOT EXISTS
(
SELECT 1 FROM Keep k
WHERE k.ID = t.ID AND k.Sub_ID = t.Sub_ID
)
这种方法应该高效且易读。
答案 1 :(得分:0)
在where子句的左侧执行转换通常会导致性能不佳。我建议在临时表中暂存要删除的行,然后在删除中简单地加入它。当您需要扩展删除条件时,只需在此临时表中添加一个插入(@delete):
declare @t table (ID int, Sub_ID int, Value int)
insert into @t
select 1234, 1, 100 union all
select 1234, 2, 50 union all
select 5678, 1, 90 union all
select 4321, 1, 75 union all
select 4321, 2, 75;
--stage the combination IDs you want to delete:
declare @delete table (ID int, Sub_ID int);
insert into @delete
select 1234, 2 union all
select 4321, 2;
delete t
from @t t
join @delete d on
t.ID = d.ID and t.Sub_ID = d.Sub_ID;
select * from @t;
答案 2 :(得分:0)
不要将您的列组合并将它们转换为字符串,这会非常慢,因为您已经注意到了。使用以下内容过滤列本身:
DELETE FROM table WHERE {
NOT((ID = x0 AND SUB_ID = y0) OR (ID = x1 AND SUB_ID = y1))
}
答案 3 :(得分:0)
该问题的可能解决方案:
看起来ID和SubID都是数字,所以不要比较字符串,而是比较数字。
创建包含ID和SubID
DELETE是一个沉重的语句,需要大量的数据库写入,并且可能会使索引碎片化。如果表足够大并且您知道要删除整个表的至少三分之一,请使用临时表并执行INSERT ... SELECT语句以将REMAINING记录插入临时表。从主表中删除所有记录,然后切换表名。您通常需要在一次交易中完成。实施前的测试表性能。 示例:Bulk DELETE on SQL Server 2008 (Is there anything like Bulk Copy (bcp) for delete data?)