2015-10-27 9 views
6

मैं निम्न क्वेरी डुप्लिकेट खिताब लौट गए हैं, लेकिन :idnil है:वापसी डुप्लिकेट रिकॉर्ड (ActiveRecord, postgres)

Movie.select(:title).group(:title).having("count(*) > 1") 

[#<Movie:0x007f81f7111c20 id: nil, title: "Fargo">, 
#<Movie:0x007f81f7111ab8 id: nil, title: "Children of Men">, 
#<Movie:0x007f81f7111950 id: nil, title: "The Martian">, 
#<Movie:0x007f81f71117e8 id: nil, title: "Gravity">] 

मैं चयन और समूह के लिए :id जोड़ने की कोशिश की लेकिन यह एक खाली सरणी देता है। मैं पूरी फिल्म रिकॉर्ड कैसे कर सकता हूं, सिर्फ शीर्षक ही नहीं?

उत्तर

12

एक एसक्यूएल-y रास्ता

पहले, ताकि रेल-विशिष्ट वाक्यविन्यास नहीं करता सिर्फ एसक्यूएल में समस्या का समाधान, चलो हमें चाल नहीं है। Finding duplicate values in a SQL Table

किलोमीटर से जवाब (दूसरा ऊपर से, इस समय गैर checkmarked,) उनकी आईडी के साथ-साथ सभी दोहराया रिकॉर्ड लौटने के अपने मानदंडों को पूरा करती:

यह तो सवाल यह एक बहुत स्पष्ट समानांतर है। मैं अपने तालिका से मिलान के किलोमीटर के एसक्यूएल संशोधित कर लिया है ...

SELECT 
    m.id, m.title 
FROM 
    movies m 
INNER JOIN (
    SELECT 
    title, COUNT(*) AS CountOf 
    FROM 
    movies 
    GROUP BY 
    title 
    HAVING COUNT(*)>1 
) dupes 
ON 
    m.title=dupes.title 

भाग INNER JOIN () अंदर अनिवार्य रूप से है क्या आप पहले से ही तैयार किया है। डुप्लिकेट शीर्षक और गणना की एक समूहीकृत तालिका। यह चाल JOIN है जो इसे 0mतालिका में आईएनजी में डालती है, जो किसी भी फिल्म को बाहर कर देगी जिसमें डुप्लिकेट की क्वेरी में मिलान नहीं है।

रेल में उत्पन्न करना इतना मुश्किल क्यों है? सबसे कठिन हिस्सा यह है कि, क्योंकि हम JOIN आईएन movies से movies हैं, हमें उपरोक्त मेरी क्वेरी में तालिका उपनाम (m और dupes बनाना होगा)।

अफसोस की बात है, यह रेल इन उपनामों को घोषित करने के किसी भी साफ तरीके प्रदान नहीं करता है। कुछ संदर्भ:

सौभाग्य से, हम में हाथ एसक्यूएल मिल गया है के बाद से, हम .find_by_sql विधि का उपयोग कर सकते हैं ...

Movie.find_by_sql("SELECT m.id, m.title FROM movies m INNER JOIN (SELECT title, COUNT(*) FROM movies GROUP BY title HAVING COUNT(*)>1) dupes ON m.first=.first") 

क्योंकि हम Movie.find_by_sql, ActiveRecord कॉल कर रहे हैं मानता है कि हमारे हाथ से लिखे गए एसक्यूएल को Movie ऑब्जेक्ट्स में बंडल किया जा सकता है। यह किसी भी मालिश या उत्पन्न नहीं करता है, जो हमें अपने उपनाम करने देता है।

इस दृष्टिकोण की इसकी कमियां हैं। यह एक सरणी देता है, न कि ActiveRecord Relation, जिसका अर्थ है कि इसे अन्य क्षेत्रों के साथ जंजीर नहीं बनाया जा सकता है। और, in the documentation for the find_by_sql method, हमें अतिरिक्त निराशा मिलती है ...

This should be a last resort because using, for example, MySQL specific terms will lock you to using that particular database engine or require you to change your call if you switch engines.

एक रेल-y रास्ता

वास्तव में, क्या एसक्यूएल ऊपर कर रहा है? यह उन नामों की एक सूची प्राप्त कर रहा है जो एक से अधिक बार प्रकट होते हैं। फिर, यह मूल तालिका के खिलाफ उस सूची से मेल खाता है। तो, चलो बस रेल का उपयोग कर ऐसा करते हैं।

titles_with_multiple = Movie.group(:title).having("count(title) > 1").count.keys 

Movie.where(title: titles_with_multiple) 

हम .keys कहते हैं क्योंकि पहली क्वेरी एक हैश देता है। चाबियाँ हमारे खिताब हैं। where() विधि एक सरणी ले सकती है, और हमने इसे शीर्षकों की एक सरणी सौंपी है। विजेता।

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

आशा है कि इससे मदद मिलती है!

+0

कमाल का जवाब, सुपर सूचनात्मक! सरणी के साथ बहुत अच्छी चाल। कहीं(), मैं प्रत्येक लूप को एक गुंजाइश करता। – Ashbury

+0

खुशी है कि मैं मदद कर सकता हूं :) :) –

0

आप अपने select में id जोड़ने की कोशिश कर सकते हैं:

Movie.select([:id, :title]).group(:title).having("count(title) > 1") 
+1

मुझे उल्लेख किया जाना चाहिए कि मैंने कोशिश की लेकिन मुझे "पीजी :: ग्रुपिंग एरर: त्रुटि: कॉलम" फिल्में.आईडी "ग्रुप बाय क्लॉज में दिखाई देनी चाहिए या एक समग्र फ़ंक्शन में उपयोग किया जाना चाहिए" – Ashbury

+0

शायद आपको अपनी आईडी जोड़नी होगी आपके समूह में भी। मैंने इसे अपडेट किया है। – akbarbin

+1

यह एक खाली सरणी देता है, मुझे लगता है क्योंकि यह डुप्लिकेट की तलाश में है: आईडी भी। :(धन्यवाद हालांकि – Ashbury

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