【问题标题】:Replacing IN clause by EXISTS causes unexpected results用 EXISTS 替换 IN 子句会导致意外结果
【发布时间】:2018-05-16 11:15:41
【问题描述】:

给定一个简单的表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 子句。但是对于存在,它不会删除正确的行,而是删除所有行,就好像'... WHERE sr.line_number...' 表达式不存在一样。

【问题讨论】:

  • 你能解释一下你打算用这个查询来完成什么吗?
  • 对于表中的每一个id_lieu,所有不属于最近十行的行都被删除。

标签: sql postgresql exists


【解决方案1】:

确保您在使用 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**);

【讨论】:

  • 谢谢,工作正常。在较低到平均的行删除(小于 5 000 000)方面或多或少相同的性能,但更好(在我的测试计算机上)。而且我认为没有像 IN 子句这样的限制。
【解决方案2】:

这是使用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

【讨论】:

  • 我试过了,性能低于之前的要求。我认为它必须为每个 id_lieu 组进行子查询,而不仅仅是一个查询。
  • @chd 。 . .即使有索引也是如此吗?
  • 是的,到目前为止,即使有索引。
猜你喜欢
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 2021-04-24
  • 2020-10-17
  • 1970-01-01
  • 2014-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多