这是关于sqlite的问题。
customers (id INTEGER PRIMARY KEY, name TEXT)
orders (id INTEGER PRIMARY KEY, cid INTEGER)
我想删除customers
中的所有重复条目(保留MAX(id)条目)。但在此之前,我想将orders
中的所有引用更改为相应的MAX(id)值。
这就是我认为正确的事情:
UPDATE orders
SET cid = (SELECT MAX(c.id)
FROM customers c
JOIN (SELECT name, id
FROM customers
WHERE id = orders.cid) q
ON c.name = q.name
GROUP BY c.name);
DELETE FROM customers
WHERE id NOT IN (SELECT MAX(id)
FROM customers
GROUP BY name);
但特别是第一个查询已经非常缓慢,已有大约10,000名客户。有更快的方法吗?
一些数字:我们有120,000个客户,其中appx。 30,000有COUNT(*)> 1(当GROUP BY名称时)。除此之外,我们还有200,000个订单。完成上述查询大约需要20分钟。
答案 0 :(得分:1)
使用临时ID表可以获得更好的性能。据我了解,SQLite在查询时遇到问题,因为每次更新和删除时,客户都会更改。请注意,此方法最适合在事务中使用。
BEGIN Transaction;
<击> CREATE Temp Table TempCustomers作为SELECT id,MAX(id)为MaxId 来自客户 GROUP BY名称; 击>
CREATE TEMP TABLE TempCustomers AS
SELECT k.id, q.MaxId
FROM customers k JOIN
(SELECT MAX(d.id) as MaxId, d.name FROM customers d GROUP BY d.name)
q ON q.name = k.name;
UPDATE orders
SET cid = (SELECT MaxId
FROM TempCustomers c
WHERE id = orders.cid);
DELETE FROM customers
WHERE id NOT IN (SELECT MaxId
FROM TempCustomers);
COMMIT;
断开连接时,Temp表将从内存中删除。或者,如果您想保持连接而不是占用内存,则可以使用DROP Temp Table
。
编辑:最终方法建议在评论中发展。
首先,向orders.cid添加索引。然后使用主键创建临时表,并将id交换插入其中(而不是动态创建)。最后,执行清理。
BEGIN Transaction;
CREATE TEMP TABLE TempCustomers
(Id Integer PRIMARY KEY,
MaxId Integer);
INSERT INTO TempCustomers SELECT k.id, q.MaxId
FROM customers k JOIN
(SELECT MAX(d.id) as MaxId, d.name FROM customers d GROUP BY d.name)
q ON q.name = k.name;
UPDATE orders
SET cid = (SELECT MaxId
FROM TempCustomers c
WHERE id = orders.cid);
DELETE FROM customers
WHERE id NOT IN (SELECT MaxId
FROM TempCustomers);
DROP TABLE TempCustomers;
COMMIT;