एक SQL-y तरीका
सबसे पहले, आइए SQL में समस्या को हल करें, ताकि रेल-विशिष्ट सिंटैक्स हमें धोखा न दे।
यह SO प्रश्न एक बहुत ही स्पष्ट समानांतर है:डुप्लिकेट ढूँढना SQL तालिका में मान
KM से उत्तर (इस समय ऊपर से दूसरा, गैर-चिह्नित, गैर-चिह्नित) सभी डुप्लिकेट रिकॉर्ड को उनकी आईडी के साथ वापस करने के आपके मानदंडों को पूरा करता है। मैंने केएम को संशोधित किया है आपके . से मेल खाने के लिए SQL टेबल...
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
इसे असंशोधित movies
. में डालें तालिका, जो ऐसी किसी भी फिल्म को बाहर कर देगी, जिसका डुप्लीकेट की क्वेरी में मिलान नहीं है।
रेल में उत्पन्न करना इतना कठिन क्यों है? सबसे मुश्किल हिस्सा यह है कि, क्योंकि हम JOIN
कर रहे हैं आईएनजी movies
movies
. के लिए , हमें टेबल एलियासेस बनाने होंगे (m
और dupes
ऊपर मेरी क्वेरी में)।
अफसोस की बात है कि यह रेल इन उपनामों को घोषित करने का कोई साफ तरीका प्रदान नहीं करता है। कुछ संदर्भ:
- रेल गिटहब समस्याएंए> "जुड़ें" और "उपनाम" का जिक्र करते हुए। दुख।
- SO प्रश्न:अलियासड टेबल के साथ ActiveRecord क्वेरी नाम
सौभाग्य से, चूंकि हमारे पास एसक्यूएल है, इसलिए हम .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 मानता है कि हमारे हाथ से लिखे गए SQL को Movie
. में बंडल किया जा सकता है वस्तुओं। यह मालिश या कुछ भी उत्पन्न नहीं करता है, जो हमें हमारे उपनाम करने देता है।
इस दृष्टिकोण में इसकी कमियां हैं। यह एक सरणी देता है न कि ActiveRecord संबंध, जिसका अर्थ है कि इसे अन्य क्षेत्रों के साथ जंजीर नहीं किया जा सकता है। और, दस्तावेज़ीकरण में find_by_sql
के लिए विधि
, हमें अतिरिक्त निराशा मिलती है...
एक रेल मार्ग
वास्तव में, SQL ऊपर क्या कर रहा है? इसे एक से अधिक बार आने वाले नामों की सूची मिल रही है। फिर, यह उस सूची को मूल तालिका से मेल कर रहा है। तो, चलिए रेल का उपयोग करके ऐसा करते हैं।
titles_with_multiple = Movie.group(:title).having("count(title) > 1").count.keys
Movie.where(title: titles_with_multiple)
हम .keys
. कहते हैं क्योंकि पहली क्वेरी हैश लौटाती है। कुंजी हमारे शीर्षक हैं। where()
विधि एक सरणी ले सकती है, और हमने इसे शीर्षकों की एक सरणी दी है। विजेता।
आप तर्क दे सकते हैं कि रूबी की एक पंक्ति दो से अधिक सुरुचिपूर्ण है। और अगर रूबी की उस एक पंक्ति में SQL की एक अधर्मी स्ट्रिंग अंतर्निहित है, तो यह वास्तव में कितना सुंदर है?
आशा है कि यह मदद करेगा!