2012-01-22 8 views
9

में डुप्लिकेट पंक्तियां हटाएं मेरे पास एक मॉडल है जहां कोड बग के कारण, डुप्लिकेट पंक्तियां हैं। अब मुझे डेटाबेस से किसी भी डुप्लिकेट को हटाने की जरूरत है।Django डीबी

प्रत्येक पंक्ति में एक अद्वितीय photo_id होना चाहिए। क्या उन्हें हटाने का कोई आसान तरीका है? या मुझे ऐसा कुछ करने की ज़रूरत है:

rows = MyModel.objects.all() 
for row in rows: 
    try: 
     MyModel.objects.get(photo_id=row.photo_id) 
    except: 
     row.delete() 
+0

यह उस क्षेत्र को परिभाषित करने के लिए बेहतर होगा, जो आपके डेटाबेस स्कीमा में अद्वितीय है। फिर आप कभी भी इस समस्या को खत्म करते हैं। वास्तव में, आपको अपने सभी डेटाबेस स्कीमा में ऐसे विवरण जोड़ना चाहिए। – Keith

उत्तर

21

सबसे आसान तरीका सबसे आसान तरीका है! खासकर एक बंद स्क्रिप्ट के लिए जहां प्रदर्शन भी कोई फर्क नहीं पड़ता (जब तक यह नहीं करता)। चूंकि यह कोर कोड नहीं है, इसलिए मैं केवल पहली चीज लिखूंगा जो दिमाग में आता है और काम करता है।

# assuming which duplicate is removed doesn't matter... 
for row in MyModel.objects.all(): 
    if MyModel.objects.filter(photo_id=row.photo_id).count() > 1: 
     row.delete() 

हमेशा की तरह, वापस ऊपर इससे पहले कि आप इस सामग्री है।

+1

धन्यवाद। क्या आप एक प्रश्न के बारे में जानते हैं जो मुझे दिखाएगा कि कौन सी पंक्तियां डुप्ली हैं? मुझे पता है कि अलग-अलग मुझे डीबी के बिना डीबी दिखाएगा, लेकिन मुझे सिर्फ डुप्लिकेट दिखाएगा? – Brenden

+0

'चुनें * तालिका समूह से फोटो_आईडी हैविंग COUNT (photo_id)> 1; ' –

+0

@brenden, पंक्तियों को हटाने के बजाय, आप उन्हें एक सूची में जोड़ सकते हैं? मैंने अपनी दूसरी क्वेरी हटा दी क्योंकि मैं भूल गया था कि डुप्लिकेट और गैर डुप्लीकेट दोनों से मेल खाता होगा ... बंद करें! –

10

यह तेज़ हो सकता है क्योंकि यह MyModel में प्रत्येक पंक्ति के लिए आंतरिक फ़िल्टर से बचाता है।

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

from django.db import connection 

query = "SELECT id FROM table_name GROUP BY unique_column HAVING COUNT(unique_column)>1" 
cursor = connection.cursor() 
cursor.execute(query) 
ids_list = [item[0] for item in cursor.fetchall()] 
अब

आप कर सकते हैं:

lastSeenId = float('-Inf') 
rows = MyModel.objects.all().order_by('photo_id') 

for row in rows: 
    if row.photo_id == lastSeenId: 
    row.delete() # We've seen this id in a previous row 
    else: # New id found, save it and check future rows for duplicates. 
    lastSeenId = row.photo_id 
+2

प्रदर्शन के बारे में, यह निश्चित रूप से बेहतर विकल्प है! धन्यवाद, हमें इसे एक बड़े डेटाबेस के लिए जरूरी था! –

+0

एक तालिका को बदलने के लिए अच्छी तरह से काम करता है ताकि 'अद्वितीय' पूरी तरह से बाधा हो, धन्यवाद! – mlissner

+0

एक और अच्छी सुविधा यह है कि यह आपको किसी अन्य क्षेत्र द्वारा ऑर्डर करने की अनुमति देता है ताकि आप डुप्स के समूह के शीर्ष पर रखना चाहें! – hobs

3

यहाँ एक तेजी से समाधान है

Some_Model.objects.filter(id__in=ids_list).delete() 

या यदि ids_list भी बड़ा अपने DBMS द्वारा नियंत्रित किया जा रहा था

आप

इसे खंडों से विभाजित कर सकते हैं जिन्हें इसे नियंत्रित किया जा सकता है:

seg_length = 100 
ids_lists = [ids_list[x:x+seg_length] for x in range(0,len(ids_list),seg_length)] 
for ids_list in ids_lists: 
    SomeModel.objects.filter(id__in=ids_list).delete() 
+0

यह डुप्लीकेट में से केवल 1 को हटा देगा।तो यदि आप किसी भी पंक्ति में से 2 से अधिक थे तो आपको इसे फिर से करना होगा। तो यह अन्य समाधानों की तुलना में तेज़ नहीं हो सकता है। – hobs