2010-09-18 32 views
1

我有一個有趣的問題,我的邏輯不能勝任這項任務。MySQL重複 - 如何指定兩個記錄實際上不重複?

我們有一張表,有時會產生重複記錄(出於工藝原因,這是不可避免的)。看看下面的例子:

id FirstName LastName PhoneNumber email 
-- --------- -------- ------------ -------------- 
1 John  Doe  123-555-1234 [email protected] 
2 Jane  Smith  123-555-1111 [email protected] 
3 John  Doe  123-555-4321 [email protected] 
4 Bob  Jones  123-555-5555 [email protected] 
5 John  Doe  123-555-0000 [email protected] 
6 Mike  Roberts 123-555-9999 [email protected] 
7 John  Doe  123-555-1717 [email protected] 

我們發現重複這樣:

SELECT c1.* 
FROM `clients` c1 
INNER JOIN (
    SELECT `FirstName`, `LastName`, COUNT(*) 
    FROM `clients` 
    GROUP BY `FirstName`, `LastName` 
    HAVING COUNT(*) > 1 
) AS c2 
ON c1.`FirstName` = c2.`FirstName` 
AND c1.`LastName` = c2.`LastName` 

這會產生重複的以下列表:

id FirstName LastName PhoneNumber email 
-- --------- -------- ------------ -------------- 
1 John  Doe  123-555-1234 [email protected] 
3 John  Doe  123-555-4321 [email protected] 
5 John  Doe  123-555-0000 [email protected] 
7 John  Doe  123-555-1717 [email protected] 

正如你所看到的,基於FirstNameLastName,所有記錄都是重複的。

在這一點上,我們實際上打電話給客戶端清除潛在的重複。

這樣做之後,我們學會(例如)的記錄1和3是真實的重複,而是記錄5和7實際上是兩個不同的人一起。

因此,我們將來自記錄1和3的任何外部鏈接的數據合併到記錄1中,刪除記錄3並單獨保留記錄5和7。

現在,這裏的人的問題就在:

下一次我們重新運行「重複」查詢時,它會包含以下行:

id FirstName LastName PhoneNumber email 
-- --------- -------- ------------ -------------- 
1 John  Doe  123-555-4321 [email protected] 
5 John  Doe  123-555-0000 [email protected] 
7 John  Doe  123-555-1717 [email protected] 

他們都顯得重複,即使我們以前認識到他們不是。

你將如何去確定這些記錄是不是重複的?

我的第一個雖然它建立一個查找表,確定哪些記錄不是彼此重複(例如,{1,5},{1,7},{5,7}),但我有不知道如何建立一個能夠使用這些數據的查詢。

此外,如果另一條重複記錄顯示出來,它可能是1,5或7的副本,所以我們需要它們全部顯示在重複列表中,以便客戶服務人員可以撥打找出他可能重複的記錄的新記錄。

我很努力去理解這一點。那裏的任何傑出的天才都會關注這個問題?

回答

1

有趣的問題。這是我的破解。

如果我們從略有不同的角度來看待問題,那麼該如何?

認爲系統是乾淨的一個開始即當前系統中的全部記錄或者與唯一的第一+姓氏的組合或相同第一+姓氏的人已經被人工確認是不同的人。

在系統中輸入NEW用戶的時候,我們會另外檢查一下。可以實現爲INSERT觸發器或插入成功完成後調用的另一個過程。

  1. 這觸發/程序的 FIRST +姓氏 組合「插入」記錄與所有現有 表中的記錄相匹配。
  2. 對於所有的匹配首先+姓氏,它會創建一個對應表(新表)與NewUserID的條目,ExistingMatchingRecordsUserID

從SQL角度來看,

TABLE MatchingTable 
COLUMNS 1. NewUserID 2. ExistingUserID 
Constraint : Logical PK = NewUserID + ExistingMatchingRecordsUserID 

INSERT INTO MATCHINGTABLE VALUES ('NewUserId', userId) 
SELECT userId FROM User u where u.firstName = 'John' and u.LastName = 'Doe' 

中的所有條目MatchingTable需要解決。

當說一個管理員登錄到系統,管理員看到在MatchingTable所有條目列表

例如:新用戶John Doe的 - (ID 345) - 3的潛在匹配John Doe的 - ID 123 ID 231/ID 256

管理員將針對123/231和256中的數據檢查數據,並手動確認是否有任何/無重複 如果重複,345從用戶表中刪除(軟/硬刪除 - 無論適合您) 如果不是,則從MatchingTable中刪除ID 354的條目(我將在這裏進行硬刪除,因爲這就像事務性臨時表一樣,但是一切都很好)。

此外,當從MatchingTable中刪除ID 354的條目時,MatchingTable中ExistingMatchingRecordsUserID = 354處的所有其他條目將自動刪除,以確保不需要對已驗證數據進行不必要的手動驗證。

同樣,這可能是一個潛在的DELETE觸發器/只是在DELETE MatchingTable上執行的邏輯。實施有偏好。

+0

這個解決方案完全符合我的需求。如果你沒有很好地概述,我真的不認爲我會找到解決方案。謝謝! – pbarney 2010-09-30 01:44:16

0

以每行向表中添加單個字節爲代價,可以添加manually_verified BOOL列,默認值爲FALSE。如果您手動驗證了數據,請將其設置爲TRUE。那麼你可以簡單地在哪裏查詢manually_verified = FALSE

它很簡單,有效,並與業務流程中實際發生的情況相匹配:手動驗證數據。

如果您想更進一步,您可能希望在行被驗證時進行存儲以及驗證該行。由於這可能令人討厭存儲在主表中,因此您可以將其存儲在單獨的表中,並在驗證數據中使用LEFT JOIN。您甚至可以創建一個視圖來重新創建單個主表的外觀。

爲了解決添加新重複的問題:您將檢查未驗證的數據與整個數據集。所以這意味着你的主表c1將具有條件manually_verified = FALSE,但是你的INNER JOIN編輯表c2不具有。這樣,未經證實的數據仍然會發現所有潛在的復配:

SELECT * FROM table t1 
INNER JOIN table t2 ON t1.name = t2.name AND t1.id <> t2.id 
WHERE t1.manually_verified = FALSE 

爲重複的可能的匹配,將在連接表。

+0

我喜歡你的方法,但是使用你建議的修改後的查詢只會顯示新的,未經驗證的記錄,而不是任何它似乎是重複的記錄。否則,我認爲這種方法會奏效。 – pbarney 2010-09-19 03:52:44

+0

那麼,你必須運行一個稍微不同的查詢... – wuputah 2010-09-19 05:29:48

+0

添加查詢結束的答案。 – wuputah 2010-09-20 00:19:04