2010-05-13 81 views
3

我想删除除了列表中的记录ID之外的所有记录。该列表的长度可以有所不同,可以很容易地包含2000+的ID,...删除除了我在Python列表中的ID以外的所有记录

目前,我将我的列表转换为一个字符串,所以它适合于这样的事情: cursor.execute(“”“从表中删除编号不在(%s)“”“,(列表)) 这感觉不对,我不知道列表允许多长时间,...

什么是最有效的方式这来自python?

用额外的字段来改变表格的结构来标记/取消标记删除记录将是很好的,但不是一个选项。 有一个专用的表存储ID的确会很有帮助,那么这可以通过一个SQL查询来完成......但我真的想尽量避免这些选项。

感谢,

+0

看到这个问题关于最大列表长度:http://stackoverflow.com/questions/855191/how-big-can-a-python-array-get/855455#855455 – 2010-05-13 11:41:09

+2

我认为更相关的限制将是MySQL端,在'NOT IN'参数字符串中。 – Amber 2010-05-13 11:45:08

回答

1

你有没有用尽SQL直接做你计算的可能性?如果是这样,我没有看到另一种方式来做到这一点,而不做你已经做的事情。可以肯定,当然,要创建有效的SQL,如果你在插上其中:

','.join(str(int(x)) for x in ids) 

你肯定是,如果直接取代你的说法。我不确定是否对NOT IN(...)子句中的ids数量有限制,但是会怀疑它,因为在使用子查询填充该列表时可以使用任意长的列表。

+0

是的,这是我在这一刻做的。我想最好的解决办法是有一些临时或专用的表。 – 2010-05-13 19:14:00

3

如果db表不是太大,只是在所有的ID读取,并 让你想删除的人的名单:

keep_ids=[...] 
cursor.execute('SELECT id FROM table') 
delete_ids=[] 
for (row_id,) in cursor: 
    if row_id not in keep_ids: 
     delete_ids.append(row_id) 
cursor.executemany('DELETE FROM table WHERE id = %s',delete_ids) 

如果db表是巨大的,然后重新创建表:

keep_ids=[...] 
cursor.execute('CREATE TABLE IF NOT EXISTS temp_table LIKE table') 
cursor.executemany('INSERT INTO temp_table (SELECT * FROM table WHERE id = %s)',keep_ids) 
cursor.execute('DROP TABLE table') 
cursor.execute('ALTER TABLE temp_table RENAME table') 
+0

有趣的想法,我会试验。 – 2010-05-13 19:15:52

-2

这就是temporary tables的用途。您创建一个包含排除列表的临时表并使用DBM为您做出选择。一个简单的例子:

CREATE TABLE words (id integer primary key not null, word string); 
CREATE TEMPORARY TABLE exclusion (word string); 
INSERT INTO words VALUES ... # 100,000 of these 
INSERT INTO exclusion VALUES ... # 1000 of these 
DELETE FROM words WHERE words.word NOT IN (SELECT word FROM exclusion); 
# 99,000 records now in words, table exclusion evaporates when the session is over 

有人谁真正知道SQL可能可以改善我的最后一行。如果您在应用程序空间中进行选择,则会出现问题。 MySQL具有临时表,但即使您没有创建/删除排除项仍然会比过长的声明更好。

顺便说一下,我在Python中黑掉了,只是因为我有一个很大的单词表。代码很无聊,所以没有发布。

+0

100,000个插入的延迟不会比具有100,000个ID的单个查询更糟吗? – apg 2010-05-13 13:21:12

+0

不知道,整个事情在我的蹩脚的桌面上花了几秒钟,这个问题也预设了数据库中已经存在table'words' – msw 2010-05-13 13:27:30

0

我想添加一个“todelete tinyint(1)not null default 1”列到表中,将它更新为0以保留那些必须保留的id,然后delete from table where todelete;。它快于不在。

或者,创建一个与您的结构相同的表,将保留的行插入并重命名表。然后,放弃旧的。

相关问题