用EXISTS替换IN子句会导致意外结果

时间:2018-05-16 11:15:42

标签: sql postgresql exists

给出一个简单的表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...'表达式不存在一样。

2 个答案:

答案 0 :(得分: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**);

答案 1 :(得分:0)

以下是使用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