在sql中比较列时如何断开连接

qlckcl4x  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(392)

我正在尝试删除postgres中的重复项。我将此作为查询的基础:

DELETE FROM case_file as p
WHERE EXISTS (
    SELECT FROM case_file as p1
    WHERE p1.serial_no = p.serial_no
    AND p1.cfh_status_dt < p.cfh_status_dt
    );

它工作得很好,除了日期 cfh_status_dt 等于则两个记录都不会被删除。
对于序列号相同且日期相同的行,我希望保留注册号相同的行(如果有,此列也有空)。
有没有一种方法可以对所有一个查询(可能是一个case语句或另一个简单的比较)执行此操作?

w6mmgewl

w6mmgewl1#

DELETE FROM case_file AS p
WHERE  id NOT IN (
   SELECT DISTINCT ON (serial_no) id  -- id = PK
   FROM   case_file 
   ORDER  BY serial_no, cfh_status_dt DESC, registration_no
   );

这将保持每行的最新一行 serial_no ,选择最小的 registration_no 如果有多个候选人。 NULL 按默认升序最后排序。所以任何一行 registration_no 首选。
如果你想要最好的 registration_no 相反,要最后对空值排序,请使用:

...
   ORDER  BY serial_no, cfh_status_dt DESC, registration_no DESC NULLS LAST

请参见:
按组选择每组中的第一行?
按列asc排序,但先为空值?
如果你没有pk( PRIMARY KEY )或其他 UNIQUE NOT NULL (组合)列可以用于此目的,可以回退到 ctid . 请参见:
如何(或如何)在多个列上选择distinct? NOT IN 通常不是最有效的方法。但它处理的是包含空值的重复项。请参见:
如何删除没有唯一标识符的重复行
如果有很多复制品-而且你能负担得起创建一个新的、原始的幸存者表并替换旧表(而不是删除现有表中的大多数行)可能(更)高效。
或者创建一个幸存者临时表,截断旧表并从临时表中插入。通过这种方式,视图或fk约束等依赖对象可以保持原位。请参见:
如何删除重复条目?
幸存的行只是:

SELECT DISTINCT ON (serial_no) *
FROM   case_file 
ORDER  BY serial_no, cfh_status_dt DESC, registration_no;

相关问题