幸运的是,您正在运行PostgreSQL。
DISTINCT ON应该使这相对容易:
由于您将删除大多数行(约90%重复),并且表很可能很容易放入RAM,因此我选择了以下方法:
SELECt
将尚存的行放入临时表中。- 重新路由引用列。
DELETE
基表中的所有行。- 重新
INSERT
幸存者。
蒸馏剩余的行
CREATE TEMP TABLE tmp ASSELECT DISTINCT ON (login_name, password) *FROM ( SELECt DISTINCT ON (email) * FROM taccounts ORDER BY email, last_login DESC ) subORDER BY login_name, password, last_login DESC;
有关更多
DISTINCT ON:
- 在每个GROUP BY组中选择第一行?
要删除两个不同条件的重复项,我只使用一个子查询,一个接一个地应用这两个规则。第一步是使用最新的保留帐户
last_login,因此这是“可序列化的”。
检查结果并测试合理性。
SELECt * FROM tmp;
在会话结束时会自动删除一个临时表。在pgAdmin(您似乎正在使用)中,会话一直存在,只要您在其中创建了临时表的编辑器窗口中打开即可。
替代查询以更新“重复项”的定义
SELECt *FROM taccounts tWHERe NOT EXISTS ( SELECt 1 FROM taccounts t1 WHERe (NULLIF(t1.email, '') = t.email OR (NULLIF(t1.login_name, ''), NULLIF(t1.password, '')) = (t.login_name, t.password) ) AND (t1.last_login, t1.account_id) > (t.last_login, t.account_id) );
这不会在任何“重复”列
NULL中将字符串(
'')视为空白或将其视为空。
行表达式
(t1.last_login,t1.account_id)考虑了两个重复可能共享相同的可能性
last_login。
account_id在这种情况下,我会选择更大的一个-这是独特的,因为它是PK。
如何识别所有传入的FK
SELECt c.confrelid::regclass::text AS referenced_table ,c.conname AS fk_name ,pg_get_constraintdef(c.oid) AS fk_definitionFROM pg_attribute a JOIN pg_constraint c ON (c.conrelid, c.conkey[1]) = (a.attrelid, a.attnum)WHERe c.confrelid = 'taccounts '::regclass -- (schema-qualified) table nameAND c.contype = 'f'ORDER BY 1, contype DESC;
或者,您可以
Dependents在选择pgAdmin的对象浏览器的右侧窗口中检查骑手
taccounts。
重新路由到新的母版
如果你有表引用
taccounts( 传入的 外键 来
taccounts),你将要更新所有这些领域, 之前 你删除受骗者。
将它们全部重新路由到新的主行:
UPDATe referencing_tbl rSET referencing_column = tmp.reference_columnFROM tmpJOIN taccounts t1 USING (email)WHERe r.referencing_column = t1.referencing_columnAND referencing_column IS DISTINCT FROM tmp.reference_column;UPDATe referencing_tbl rSET referencing_column = tmp.reference_columnFROM tmpJOIN taccounts t2 USING (login_name, password)WHERe r.referencing_column = t1.referencing_columnAND referencing_column IS DISTINCT FROM tmp.reference_column;
进去杀人
现在,这些骗子不再有链接。进去杀人。
ALTER TABLE taccounts DISABLE TRIGGER ALL;DELETe FROM taccounts;VACUUM taccounts;INSERT INTO taccountsSELECt * FROM tmp;ALTER TABLE taccounts ENABLE TRIGGER ALL;
我在操作过程中禁用了所有触发器。这样可以避免在操作过程中检查参照完整性。重新激活触发器后,一切都应该正常。我们已经处理了上面所有 传入的
FK。由于您没有并发访问权限并且所有值以前都在那里,因此保证 传出 FK声音良好。



