2010-02-09 25 views
25

मैंने इसके लिए कुछ समाधान देखे हैं, लेकिन मुझे आश्चर्य है कि तालिका को डी-डुप्लिकेट करने का सबसे अच्छा और सबसे प्रभावी तरीका क्या है। आप अपने बिंदु को चित्रित करने के लिए कोड (एसक्यूएल, इत्यादि) का उपयोग कर सकते हैं, लेकिन मैं केवल मूल एल्गोरिदम की तलाश में हूं। मैंने माना कि एसओ पर इसके बारे में पहले से ही एक सवाल होगा, लेकिन मैं एक नहीं ढूंढ पाया, इसलिए यदि यह पहले से मौजूद है तो मुझे सिर्फ एक सिर दें।तालिका को समर्पित करने का सबसे अच्छा तरीका क्या है?

(बस स्पष्ट करने के लिए - मैं एक वृद्धिशील स्वत: पी है और जो किसी तालिका में डुप्लिकेट से छुटकारा पाने की बात कर रहा हूँ कुछ पंक्तियाँ है कि सब कुछ है, लेकिन पी क्षेत्र में डुप्लिकेट हैं है।)

+0

आप (पी को छोड़कर) * समान * डुप्लिकेट गिर मतलब, या गिर * पर्याप्त समान * डुप्लिकेट है? पूर्व को काफी सरलता से किया जा सकता है, उत्तरार्द्ध अनिश्चितता और दर्द की एक संभावित दुनिया है। –

+0

@j_random_hacker - मेरा मतलब पूरी तरह से समान था। पोस्ट के शब्द को देखें - "मैं डुप्लीकेट से छुटकारा पाने का जिक्र कर रहा हूं ... पंक्तियां जो * सबकुछ * पीके फ़ील्ड * में डुप्लिकेट हैं।" – froadie

+0

क्षमा करें, मैंने सावधानीपूर्वक पर्याप्त नहीं पढ़ा ... –

उत्तर

1

आप एक उत्पन्न कर सकता है प्रत्येक पंक्ति के लिए हैश (पीके को छोड़कर), इसे एक नए कॉलम में स्टोर करें (या यदि आप नए कॉलम नहीं जोड़ सकते हैं, तो क्या आप टेबल को एक अस्थायी स्टेजिंग क्षेत्र में ले जा सकते हैं?), और उसके बाद अन्य सभी पंक्तियों को देखें हैश। बेशक, आपको यह सुनिश्चित करने में सक्षम होना होगा कि आपके हैश फ़ंक्शन अलग-अलग पंक्तियों के लिए समान कोड नहीं बनाते हैं।

यदि दो पंक्तियां डुप्लिकेट हैं, तो क्या इससे कोई फर्क पड़ता है कि आप किससे छुटकारा पा रहे हैं? क्या यह संभव है कि अन्य डेटा दोनों डुप्लीकेट पर निर्भर हैं? यदि हां, तो आप कुछ ही चरणों के माध्यम से जाना होगा:

  • ड्यूप्स खोजें
  • उनमें से किसी एक को चुनें dupeA के रूप में समाप्त करने के लिए
  • पर dupeA
  • ऑल्टर कि डेटा उल्लेख करने के लिए सभी डेटा निर्भर खोजें dupeB
  • dupeA हटाएं।

यह आपके मौजूदा डेटा मॉडल के आधार पर आसान या जटिल हो सकता है।

यह पूरा परिदृश्य रखरखाव और रीडिज़ाइन प्रोजेक्ट की तरह लगता है। यदि हां, तो शुभकामनाएं !!

+0

दें कि आप वास्तव में कैसे सुनिश्चित करते हैं कि हैश डॉन विभिन्न डेटा के लिए एक ही कोड का उत्पादन नहीं करते हैं। हैश का उपयोग करते समय हमेशा डुप्लिकेट की संभावना होती है। Downvote। –

+0

@EsbenP: मैं ज़िपित मूल तार के लिए हैश का एक प्रकार के रूप में इस्तेमाल तार देखा है। कम से कम आपको डुप्लिकेट नहीं मिलते हैं। – FrustratedWithFormsDesigner

+0

मैं मान रहा था कि कोई अन्य डेटा पीके क्षेत्र पर निर्भर नहीं है। लेकिन यह एक दिलचस्प बात है - अगर ऐसा होता तो आप क्या करेंगे? इससे यह एक बहुत अधिक जटिल हो जाएगा ... कोई विचार? – froadie

0

एसक्यूएल के लिए, आप तालिका में INSERT IGNORE का उपयोग कर सकते हैं SELECT xy से unkeyed_table;

एल्गोरिदम के लिए, यदि आप मान सकते हैं कि प्राथमिक कुंजी को दोहराया जा सकता है, लेकिन एक प्राथमिक-कुंजी-कुंजी विशिष्ट रूप से पंक्ति की सामग्री को पहचानती है, हैश की तुलना में केवल प्राथमिक कुंजी और पुनरावृत्ति की जांच करें।

0

मुझे लगता है कि इसे आईडी के अलावा सभी कॉलमों द्वारा समूहित करने और प्रत्येक समूह से एक पंक्ति चुनने के लिए कुछ भी नहीं चाहिए - सादगी के लिए केवल पहली पंक्ति के लिए, लेकिन यह वास्तव में आपके लिए आईडी पर अतिरिक्त बाधाओं के अलावा कोई फर्क नहीं पड़ता।

या अन्य तरीकों से पंक्तियों से छुटकारा पाने के लिए ... बस सभी पंक्तियों को सभी समूहों से एक को स्वीकार करें हटा दें।

7

SELECT DISTINCT <insert all columns but the PK here> FROM foo। उस क्वेरी का उपयोग करके एक अस्थायी तालिका बनाएं (सिंटैक्स आरडीबीएमएस द्वारा भिन्न होता है लेकिन आमतौर पर SELECT … INTO या CREATE TABLE AS पैटर्न उपलब्ध है), फिर पुरानी तालिका को उड़ाएं और डेटा को वापस टेम्प्लेट टेबल से पंप करें।

8

डेडअपिंग शायद ही कभी सरल है। ऐसा इसलिए है क्योंकि रिकॉर्ड को तोड़ने के लिए अक्सर कुछ अलग-अलग मान होते हैं। इसलिए चुनें कि कौन सा रिकॉर्ड रखना मुश्किल हो सकता है। इसके अलावा, डुप्लिकेट अक्सर लोग रिकॉर्ड करते हैं और यह पहचानना मुश्किल है कि क्या दो जॉन स्मिथ दो लोग हैं या एक व्यक्ति जो डुप्लिकेट किया गया है। इसलिए अपने समय के बारे में बहुत कुछ (50% या अधिक परियोजना) खर्च करें जो परिभाषित करता है कि क्या एक डुप्लिकेट और अंतर और बाल रिकॉर्ड को संभालने का तरीका है।

आप कैसे जानते हैं कि सही मूल्य कौन सा है? आगे dedupping की आवश्यकता है कि आप सभी बच्चे के रिकॉर्ड संभाल नहीं है किसी भी अनाथ नहीं। क्या होता है जब आप पाते हैं कि बच्चे के रिकॉर्ड पर आईडी को बदलकर आप अचानक एक अद्वितीय इंडेक्स या बाधाओं का उल्लंघन कर रहे हैं - यह अंततः होगा और आपकी प्रक्रिया को इसे संभालने की आवश्यकता है। यदि आपने अपनी सभी बाधाओं को लागू करने के लिए मूर्खतापूर्वक चुना है, तो आवेदन को पूरी तरह से पूरा करें, आपको यह भी पता नहीं हो सकता कि बाधाओं का उल्लंघन किया जाता है। जब आपके पास कटौती के लिए 10,000 रिकॉर्ड हैं, तो आप एक समय में एक को समर्पित करने के लिए आवेदन के माध्यम से नहीं जा रहे हैं। यदि बाधा डेटाबेस में नहीं है, तो जब आप dedup करते हैं तो डेटा अखंडता को बनाए रखने में बहुत भाग्य।

एक और जटिलता यह है कि डुप्लिकेट हमेशा नाम या पते पर बिल्कुल मेल नहीं खाते हैं। उदाहरण के लिए जोआन मार्टिन नामक एक विक्रय प्रतिनिधि बिक्री प्रतिनिधि नाम जोन मार्टिन-जोन्स का एक डुप्लिकेट हो सकता है, खासकर यदि उनके पास एक ही पता और ईमेल है। या आप नाम में जॉन या जॉनी हो सकता है। या एक ही सड़क के पते को छोड़कर एक ही सड़क का पता लगाया गया एसटी। और एक स्ट्रीट बाहर वर्तनी। एसक्यूएल सर्वर में आप एसएसआईएस और फ़ज़ी ग्रुपिंग का उपयोग निकटतम मैचों की पहचान करने के लिए भी कर सकते हैं। ये अक्सर सबसे आम डुप्लिकेट हैं क्योंकि तथ्य यह नहीं था कि सटीक मिलान नहीं थे, इसलिए उन्हें पहली जगह में डुप्लिकेट के रूप में रखा गया।

कुछ प्रकार के dedupping के लिए, आपको एक उपयोगकर्ता इंटरफ़ेस की आवश्यकता हो सकती है, ताकि dedupping करने वाला व्यक्ति किसी विशेष फ़ील्ड के लिए उपयोग करने के लिए दो मूल्यों का चयन कर सके। यह विशेष रूप से सच है यदि वह व्यक्ति जो कटौती की जा रही है वह दो या दो से अधिक भूमिकाओं में है। यह हो सकता है कि किसी विशेष भूमिका के लिए डेटा आमतौर पर किसी अन्य भूमिका के डेटा से बेहतर होता है। या यह हो सकता है कि केवल उपयोगकर्ता ही यह सुनिश्चित कर सकें कि सही मूल्य क्या है या उन्हें यह पता लगाने के लिए लोगों से संपर्क करने की आवश्यकता हो सकती है कि वे वास्तव में डुप्लिकेट हैं या केवल एक ही नाम वाले दो लोग हैं।

1

आप में से जो लोग एक त्वरित और गंदा प्रक्रिया अपनाते हैं के लिए, बस सभी स्तंभों है कि एक साथ एक विशिष्ट रिकॉर्ड को परिभाषित करने और उन स्तंभों के साथ एक अद्वितीय सूचकांक बनाने के लिए, तो जैसे सूची:

ALTER ध्यान न दें टेबल TABLE_NAME जोड़ें अद्वितीय (column1, column2, column3)

आप अनन्य अनुक्रमणिका बाद में छोड़ सकते हैं।

3

यहाँ विधि का उपयोग मैं आप बयान से एक समूह में अपने शिकार मापदंड प्राप्त कर सकते हैं और अपनी मेज विशिष्टता के लिए एक आईडी पहचान स्तंभ है:,

delete t 
from tablename t 
inner join 
(
    select date_time, min(id) as min_id 
    from tablename 
    group by date_time 
    having count(*) > 1 
) t2 on t.date_time = t2.date_time 
where t.id > t2.min_id 

इस उदाहरण में DATE_TIME समूहीकरण मापदंड है अगर आपके पास एक से अधिक कॉलम हैं जो उन सभी में शामिल होने के लिए सुनिश्चित हैं।

+0

मुझे यह पसंद है। मैंने अभी कोशिश की और यह मेरे लिए बहुत अच्छा काम करता है। –

+0

शानदार समाधान! धन्यवाद! –

1

मैं डीशूक से एक ले रहा हूं और एक dedupe उदाहरण प्रदान कर रहा हूं जहां आप केवल उच्चतम तारीख के साथ रिकॉर्ड रखेंगे।

इस उदाहरण में कहते हैं कि मैं सभी एक ही APP_ID साथ 3 रिकॉर्ड है, और मुझे केवल उच्चतम तारीख के साथ एक रखना चाहते हैं:

DELETE t 
FROM @USER_OUTBOX_APPS t 
INNER JOIN 
(
    SELECT 
     app_id 
     ,max(processed_date) as max_processed_date 
    FROM @USER_OUTBOX_APPS 
    GROUP BY app_id 
    HAVING count(*) > 1 
) t2 on 
    t.app_id = t2.app_id 
WHERE 
    t.processed_date < t2.max_processed_date 
0

यह c1 में दोहराया मूल्यों डेड्यूप कर सकते हैं:

select * from foo 
minus 
select f1.* from foo f1, foo f2 
where f1.c1 = f2.c1 and f1.c2 > f2.c2 
7

विश्लेषणात्मक समारोह ROW_NUMBER का उपयोग करना:

WITH CTE (col1, col2, dupcnt) 
AS 
(
SELECT col1, col2, 
ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col1) AS dupcnt 
FROM Youtable 
) 
DELETE 
FROM CTE 
WHERE dupcnt > 1 
GO                 
0

यहाँ एक है मैंने वास्तविक जीवन में भाग लिया है।

मान लें कि उपयोगकर्ताओं के बाहरी/3 पार्टी लॉगिन की एक तालिका है, और आप दो उपयोगकर्ताओं विलय और प्रदाता/प्रदाता कुंजी मान पर डेड्यूप करना चाहते हैं जा रहे हैं।

;WITH Logins AS 
    (
     SELECT [LoginId],[UserId],[Provider],[ProviderKey] 
     FROM [dbo].[UserLogin] 
     WHERE [UserId][email protected] -- is the user we're deleting 
       OR [UserId][email protected] -- is the user we're moving data to 
    ), Ranked AS 
    (
     SELECT Logins.* 
      , [Picker]=ROW_NUMBER() OVER (
         PARTITION BY [Provider],[ProviderKey] 
         ORDER BY CASE WHEN [UserId][email protected] THEN 1 ELSE 0 END) 
     FROM Logins 
    ) 
    MERGE Logins AS T 
    USING Ranked AS S 
    ON S.[LoginId]=T.[LoginID] 
    WHEN MATCHED AND S.[Picker]>1 -- duplicate Provider/ProviderKey 
       AND T.[UserID][email protected] -- safety check 
    THEN DELETE 
    WHEN MATCHED AND S.[Picker]=1 -- the only or best one 
       AND T.[UserID][email protected] 
    THEN UPDATE SET T.[UserID][email protected] 
    OUTPUT $action, DELETED.*, INSERTED.*; 
5

भविष्य में संदर्भ के लिए यहाँ वास्तविक कोड जोड़ना

तो, वहाँ 3 चरणों, और इसलिए 3 SQL कथन हैं:

चरण 1: एक अस्थायी में गैर डुप्लिकेट (अद्वितीय tuples) ले जाएँ तालिका

CREATE TABLE new_table as 
SELECT * FROM old_table WHERE 1 GROUP BY [column to remove duplicates by]; 

चरण 2: पुराने तालिका को हटाने (या उसका नाम बदल) हम अब सभी डुप्लिकेट प्रविष्टियों के साथ टेबल चाहिए, इसलिए इसे छोड़!

DROP TABLE old_table; 

चरण 3: old_table

RENAME TABLE new_table TO old_table; 

और निश्चित रूप से, उनके नाम के new_table नाम बदलें, मत भूलना डुप्लिकेट डालने रोकने के लिए अपने गाड़ी कोड तय करने के लिए!

0

इन विधियों काम करेंगे, लेकिन एक पी के रूप में एक स्पष्ट आईडी के बिना तो कौन-सी पंक्तियां का निर्धारण करने के लिए एक समस्या हो सकती है हटाने के लिए। एक अस्थायी तालिका में उछाल मूल से हटाएं और डुप्लिकेट के बिना पुनः डालें सबसे आसान लगता है।

संबंधित मुद्दे