用 EXISTS 替换 IN 子句会导致意外结果
Replacing IN clause by EXISTS causes unexpected results
给定一个简单的 table lieu_horaire 和 :
+ id_horaire (numeric)
+ id_lieu (numeric)
+ horaire (timestamp)
以下查询目前工作正常:
DELETE FROM lieu_horaire where id_horaire IN (
SELECT id_horaire "+
FROM (
SELECT id_horaire,
ROW_NUMBER() OVER (PARTITION BY id_lieu order by horaire desc) AS line_number
FROM lieu_horaire
) as sr
WHERE sr.line_number > 10);
但是由于可扩展性的原因,我想用 EXISTS '... WHERE EXISTS(... '
替换 IN 子句。但是对于 exists,它不会删除正确的行,而是删除所有行,就好像 '... WHERE sr.line_number...'
表达式不存在一样。
这里是使用 NOT IN
的简化:
DELETE FROM lieu_horaire lh
WHERE lh.id_horaire NOT IN (SELECT lh2.id_horaire
FROM lieu_horaire lh2
WHERE lh2.id_lieu = lh.id_lieu
ORDER BY lh2.horaire DESC
LIMIT 10
);
不过,不知道性能会好多少。对于任一版本,您都需要 lieu_horaire(id_lieu, horaire)
.
上的索引
如果要删除大量行,我可能建议改为 truncate
/insert
。
确保您在使用 exists 时加入了专栏,如下所示:
DELETE FROM lieu_horaire where exists (
SELECT id_horaire
FROM (
SELECT id_horaire,
ROW_NUMBER() OVER (PARTITION BY id_lieu order by horaire desc) AS line_number
FROM lieu_horaire
) as sr
WHERE sr.line_number > 10 **and lieu_horaire.id_horaire=sr.id_horaire**);
给定一个简单的 table lieu_horaire 和 :
+ id_horaire (numeric)
+ id_lieu (numeric)
+ horaire (timestamp)
以下查询目前工作正常:
DELETE FROM lieu_horaire where id_horaire IN (
SELECT id_horaire "+
FROM (
SELECT id_horaire,
ROW_NUMBER() OVER (PARTITION BY id_lieu order by horaire desc) AS line_number
FROM lieu_horaire
) as sr
WHERE sr.line_number > 10);
但是由于可扩展性的原因,我想用 EXISTS '... WHERE EXISTS(... '
替换 IN 子句。但是对于 exists,它不会删除正确的行,而是删除所有行,就好像 '... WHERE sr.line_number...'
表达式不存在一样。
这里是使用 NOT IN
的简化:
DELETE FROM lieu_horaire lh
WHERE lh.id_horaire NOT IN (SELECT lh2.id_horaire
FROM lieu_horaire lh2
WHERE lh2.id_lieu = lh.id_lieu
ORDER BY lh2.horaire DESC
LIMIT 10
);
不过,不知道性能会好多少。对于任一版本,您都需要 lieu_horaire(id_lieu, horaire)
.
如果要删除大量行,我可能建议改为 truncate
/insert
。
确保您在使用 exists 时加入了专栏,如下所示:
DELETE FROM lieu_horaire where exists (
SELECT id_horaire
FROM (
SELECT id_horaire,
ROW_NUMBER() OVER (PARTITION BY id_lieu order by horaire desc) AS line_number
FROM lieu_horaire
) as sr
WHERE sr.line_number > 10 **and lieu_horaire.id_horaire=sr.id_horaire**);