2011-11-18 14 views
75

SQLite3 में - मेरे पास एक विशाल तालिका - 36 मिलियन पंक्तियां हैं। पाठ SQLite डेटाबेस से डुप्लिकेट पंक्तियों को हटाने

  • घ - - असली
  • हालांकि, पंक्तियों के कुछ डुप्लिकेट हैं

    यह बहुत बड़ी तालिका में, वहाँ दो कॉलम

    • हैश कर रहे हैं। यही है, हैश और डी दोनों के समान मूल्य हैं।

      इसके अलावा, अगर दो हैश समान हैं, इसलिए घ के मूल्यों, लेकिन दो समान डी एस वैसे भी दो समान हैश

      संकेत नहीं करता है, मैं डुप्लीकेट पंक्तियों हटाना चाहते हैं। मेरे पास प्राथमिक कुंजी कॉलम नहीं है। ऐसा करने का सबसे तेज़ तरीका क्या है?


      संपादित करें: delete from dist where rowid not in (select max(rowid) from dist group by hash);

      चाल करने के लिए प्रकट होता है।

    +2

    +1 आपके 'EDIT' ने अपना बहुत समय बचा लिया है ... :) – Ankur

    +0

    सहमत हैं। @ पैच EDIT मेरे लिए सीधे काम करता है –

    +1

    आत्म-जागरूक टिप्पणियों से प्यार होना चाहिए: "मेरे पास प्राथमिक कुंजी कॉलम नहीं है क्योंकि मैं मूर्ख हूं" :) – dwanderson

    उत्तर

    94

    आपको पंक्तियों को अलग करने के लिए एक तरीका चाहिए। आपकी टिप्पणी के आधार पर, आप इसके लिए विशेष rowid column का उपयोग कर सकते हैं।

    रखकर डुप्लिकेट को हटाने के लिए सबसे कम rowid(hash,d) प्रति:

    delete from YourTable 
    where rowid not in 
         (
         select min(rowid) 
         from YourTable 
         group by 
           hash 
         ,  d 
         ) 
    
    +0

    SQLite आपको प्राथमिक कुंजी कॉलम जोड़ने नहीं देता है, है ना? – Patches

    +0

    'sqlite> तालिका dist को बदलें आईडी पूर्णांक प्राथमिक कुंजी autoincrement जोड़ें; त्रुटि: प्राथमिक कुंजी कॉलम ' – Patches

    +0

    दिलचस्प नहीं जोड़ सकता है! आपको जिस हिस्से की आवश्यकता है वह 'autoincrement' है, हालांकि यह काम करता है यदि आप 'प्राथमिक कुंजी' भाग को छोड़ देते हैं? – Andomar

    1

    यदि प्राथमिक कुंजी जोड़ना एक विकल्प नहीं है, तो एक दृष्टिकोण एक टेम्पलेट तालिका में डुप्लिकेट DISTINCT को संग्रहीत करना होगा, मौजूदा तालिका से सभी डुप्लीकेट रिकॉर्ड्स को हटाएं, और फिर रिकॉर्ड्स को मूल तालिका में जोड़ें अस्थायी तालिका से।

    उदाहरण के लिए (एसक्यूएल सर्वर 2008 के लिए लिखा है, लेकिन तकनीक किसी भी डेटाबेस के लिए एक ही है):

    DECLARE @original AS TABLE([hash] varchar(20), [d] float) 
    INSERT INTO @original VALUES('A', 1) 
    INSERT INTO @original VALUES('A', 2) 
    INSERT INTO @original VALUES('A', 1) 
    INSERT INTO @original VALUES('B', 1) 
    INSERT INTO @original VALUES('C', 1) 
    INSERT INTO @original VALUES('C', 1) 
    
    DECLARE @temp AS TABLE([hash] varchar(20), [d] float) 
    INSERT INTO @temp 
    SELECT [hash], [d] FROM @original 
    GROUP BY [hash], [d] 
    HAVING COUNT(*) > 1 
    
    DELETE O 
    FROM @original O 
    JOIN @temp T ON T.[hash] = O.[hash] AND T.[d] = O.[d] 
    
    INSERT INTO @original 
    SELECT [hash], [d] FROM @temp 
    
    SELECT * FROM @original 
    

    मुझे यकीन है कि अगर SQLite एक ROW_NUMBER() प्रकार कार्य है नहीं कर रहा हूँ, लेकिन आप कर सकते थे अगर यह होता है यहां सूचीबद्ध कुछ दृष्टिकोणों को भी आजमाएं: Delete duplicate records from a SQL table without a primary key

    +0

    +1, सुनिश्चित नहीं है कि sqlite

    से हटाएं 'वाक्यविन्यास हालांकि – Andomar

    4

    मुझे लगता है कि सबसे तेजी से बहुत डेटाबेस का उपयोग करने के लिए यह होगा: एक ही कॉलम के साथ एक नई तालिका जोड़ने के लिए, लेकिन उचित बाधाओं के साथ (हैश/असली जोड़ी पर एक अनूठी अनुक्रमणिका?), मूल तालिका के माध्यम से पुनरावृत्ति करें और बाधा उल्लंघन त्रुटियों को अनदेखा करते हुए, नई तालिका में रिकॉर्ड डालने का प्रयास करें (यानी अपवाद उठाए जाने पर पुनरावृत्ति जारी रखें)।

    फिर पुरानी तालिका हटाएं और पुराने को नए नाम दें।

    +0

    बस तालिका को बदलने के रूप में सुरुचिपूर्ण नहीं है, मुझे लगता है, लेकिन आपके दृष्टिकोण के बारे में वास्तव में एक अच्छी बात यह है कि आप स्रोत डेटा को छूने/नष्ट किए बिना जितनी बार चाहें उतनी बार फिर से चला सकते हैं जब तक कि आप बिल्कुल खुश नहीं होते परिणाम है। –

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