在單個表中查找特定列中的值幾乎重複的行
我在 RDS 上有一個 Postgres 11 表,其中包含一列
$$ and only that column $$顯然是事實上的重複,但大小寫不同,即不同的大小寫,例如:
foo@****.com Foo@****.com
需要明確的是,目前的行都不是真正的重複,也不是在該列中共享完全相同的值。我的目標是辨識這些記錄
$$ and, once found, eliminate/merge the de-facto duplicates $$. 我最初的傾向是使用自連接,例如:
SELECT c.email FROM schema.table c INNER JOIN schema.table d ON lower(c.email) = lower(d.email) ORDER BY c.email;
但是,這會返回所有電子郵件記錄,而不僅僅是那些事實上的重複記錄。
使用如下子查詢會產生類似的
$$ i.e., too-inclusive $$結果:
SELECT c.email, alias.email FROM schema.table c JOIN (SELECT email FROM schema.table) alias ON lower(c.email) = lower(alias.email);
由於我不是在尋找一個聚合,而是一個不區分大小寫的比較,所以在我看來,視窗函式不是正確的方法。
我認為這應該是一個直截了當的查詢,但我很難清楚地看到它,並且我確信我在構思問題的方式上存在錯誤;這很令人沮喪。
除了在這里和 SO 上搜尋之外,我還查閱了 Molinaro 的SQL Cookbook,但無濟於事。
構造查詢的正確方法是什麼,以便它只返回那些
編輯說明:我最初的問題表述表達了使用 ILIKE 進行不區分大小寫匹配的錯誤傾向,但是按照以下答案中的建議使用 lower() 更為明智
另一個案例
EXISTS
:SELECT * FROM schema.table t WHERE EXISTS ( SELECT FROM schema.table t1 WHERE lower(t.email) = lower(t1.email) AND t.ctid <> t1.ctid ) ORDER BY lower(email), email;
如果您有 PK,請使用它而不是
ctid
. 有關的:這將返回每個符合條件的行一次。添加的內容
ORDER BY
有助於將欺騙者保持在一起並保持確定的排序順序(除非您的語言環境不區分大小寫)。為什麼不使用簡單的連接? 例如,如果您有同一封電子郵件的 10 個變體,一個簡單的連接將給您10 over 2 = 90 行,並以相反的角色重複每個組合。基本上是每組騙子的所有騙子的有限Carthesian 乘積。
有關的:
那裡建議的三元組索引應該極大地幫助處理非平凡大小的表的性能。
另請注意,
lower(t.email) = lower(t1.email)
與 略有不同t.email ILIKE t1.email
。後者將右側視為模式,其中某些字元具有特殊含義,除非您對其進行轉義。看: