Sqlite डेटाबेस से डुप्लिकेट पंक्तियों को हटाना


91

मेरे पास एक विशाल तालिका है - 36 मिलियन पंक्तियाँ - SQLite3 में। इस बहुत बड़ी तालिका में, दो कॉलम हैं:

  • hash - पाठ
  • d - असली

कुछ पंक्तियाँ डुप्लिकेट हैं। अर्थात दोनों hashका dमान समान है। यदि दो हैश समान हैं, तो इसके मूल्य हैं d। हालांकि, दो समान समान dनहीं हैं, दो समान है hash

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

ऐसा करने का सबसे तेज़ तरीका क्या है?


कृपया उत्तर ब्लॉक में रखें। बाद में, आप अपना खुद का उत्तर स्वीकार कर सकते हैं। यह भी देखें कि उत्तर के काम को कैसे स्वीकार किया जाता है?
jww

जवाबों:


120

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

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

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

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

sqlite> alter table dist add id integer primary key autoincrement; Error: Cannot add a PRIMARY KEY column
पैच

दिलचस्प! autoincrementहालांकि आपको जिस भाग की आवश्यकता होती है , वह primary keyभाग छूटने पर काम करता है ?
एंडोमर

sqlite> alter table dist add id integer autoincrement; Error: near "autoincrement": syntax error संपादित करें: SQLite में "पंक्तिबद्ध" छद्म स्तंभ प्रकार की चीज़ है जो स्वचालित रूप से वहाँ है, क्या मैं इसका उपयोग कर सकता हूं?
पैच

1
delete from dist where rowid not in (select max(rowid) from dist group by hash); चाल करने के लिए प्रकट होता है! धन्यवाद।
पैच

5

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

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


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

1

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

उदाहरण के लिए (SQL Server 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()प्रकार्य है, लेकिन अगर ऐसा होता है तो आप यहां सूचीबद्ध कुछ तरीकों को भी आज़मा सकते हैं: प्राथमिक कुंजी के बिना SQL तालिका से डुप्लिकेट रिकॉर्ड हटाएं


+1, निश्चित नहीं है कि यदि delete <alias> from <table> <alias>
साइक्लाइट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.