सक्रिय रिकॉर्ड, रेल और पोस्टग्रेज के साथ कई डुप्लिकेट फ़ील्ड वाली पंक्तियाँ ढूंढें


103

Postgres, और Activerecord का उपयोग करके कई कॉलमों में डुप्लिकेट मानों के साथ रिकॉर्ड खोजने का सबसे अच्छा तरीका क्या है?

मुझे यह समाधान यहां मिला :

User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )

लेकिन यह पोस्टग्रेज के साथ काम नहीं करता है। मुझे यह त्रुटि मिल रही है:

PG :: GroupingError: ERROR: column "parts.id" को GROUP BY में क्लॉज में प्रकट होना चाहिए या एक समग्र फ़ंक्शन में उपयोग किया जाना चाहिए


3
नियमित एसक्यूएल में, मैं सेल्फ-जॉइन का उपयोग करता हूं, जैसे कुछ select a.id, b.id, name, email FROM user a INNER JOIN user b USING (name, email) WHERE a.id > b.id। कोई विचार नहीं है कि ActiveRecord-Speak में कैसे व्यक्त किया जाए।
क्रेग रिंगर

जवाबों:


223

परीक्षण और कार्य संस्करण

User.select(:first,:email).group(:first,:email).having("count(*) > 1")

इसके अलावा, यह थोड़ा असंबंधित लेकिन आसान है। यदि आप देखना चाहते हैं कि प्रत्येक संयोजन को कितनी बार मिला है, तो अंत में इसे आकार दें:

User.select(:first,:email).group(:first,:email).having("count(*) > 1").size

और आपको एक परिणाम सेट मिलेगा जो इस तरह दिखता है:

{[nil, nil]=>512,
 ["Joe", "test@test.com"]=>23,
 ["Jim", "email2@gmail.com"]=>36,
 ["John", "email3@gmail.com"]=>21}

सोचा कि यह बहुत अच्छा था और इसे पहले नहीं देखा था।

टैरिन को श्रेय, यह उसके जवाब का सिर्फ एक साझा संस्करण है।


7
मुझे काम करने के क्रम select()में एक अन्वेषण सरणी पास करनी थी User.select([:first,:email]).group(:first,:email).having("count(*) > 1").count
राफेल ओलिवेरा

4
जोड़ .countदेता हैPG::UndefinedFunction: ERROR: function count
मैग्ने

1
आप User.select ([: पहला,: ईमेल]) की कोशिश कर सकते समूह (: पहला,: ईमेल) .having ( "गिनती (*)> 1")
Serhii Nadolynskyi

3
मैं एक ही विधि की कोशिश कर रहा हूँ, लेकिन साथ ही User.id प्राप्त करने की कोशिश कर रहा हूँ, इसे चयन और समूह में जोड़कर एक खाली सरणी देता है। मैं पूरे उपयोगकर्ता मॉडल को कैसे वापस कर सकता हूं, या कम से कम: आईडी शामिल कर सकता हूं?
एशबरी

5
.sizeइसके बजाय का उपयोग करें.count
चार्ल्स हैमेल

32

यह त्रुटि तब होती है क्योंकि POSTGRES को आपको सेलेक्ट क्लॉज में ग्रुपिंग कॉलम रखना पड़ता है।

प्रयत्न:

User.select(:first,:email).group(:first,:email).having("count(*) > 1").all

(ध्यान दें: परीक्षण नहीं किया गया है, आपको इसे ट्विक करने की आवश्यकता हो सकती है)

आईडी कॉलम को हटाने का कार्य


7
वह काम करने वाला नहीं है; idस्तंभ, समूह का हिस्सा नहीं है, तो आप इसे का उल्लेख नहीं कर सकते जब तक आप इसे कुल (जैसे array_agg(id)या json_agg(id))
क्रेग रिंगर

9

यदि आपको पूर्ण मॉडल की आवश्यकता है, तो निम्न का प्रयास करें (@ newUserNameHere के उत्तर के आधार पर)।

User.where(email: User.select(:email).group(:email).having("count(*) > 1").select(:email))

यह उन पंक्तियों को लौटा देगा जहाँ पंक्ति का ईमेल पता अद्वितीय नहीं है।

मैं कई विशेषताओं पर ऐसा करने के तरीके से अवगत नहीं हूँ।


`` `User.where (ईमेल: User.select (: ईमेल) .group (: ईमेल) .having (" गिनती (*)> 1 "))` ``
chet कोरी

धन्यवाद कि महान काम करता है :) यह भी लगता है जैसे यह अंतिम .select(:email)बेमानी है। मुझे लगता है कि यह थोड़ा साफ है, लेकिन मैं गलत हो सकता है। User.where(email: User.select(:email).group(:email).having("count(*) > 1"))
chet कोरी

2

यदि आप PostgreSQL का उपयोग करते हैं, तो एक ही क्वेरी के साथ सभी डुप्लिकेट प्राप्त करें :

def duplicated_users
  duplicated_ids = User
    .group(:first, :email)
    .having("COUNT(*) > 1")
    .select('unnest((array_agg("id"))[2:])')

  User.where(id: duplicated_ids)
end

irb> duplicated_users

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.