অ্যাক্টিভ রেকর্ড, রেলস এবং পোস্টগ্রিস সহ একাধিক সদৃশ ক্ষেত্র সহ সারিগুলি সন্ধান করুন


103

পোস্টগ্রিস এবং অ্যাক্টিভেকর্ড ব্যবহার করে একাধিক কলামে সদৃশ মানগুলির সাথে রেকর্ডগুলি সন্ধান করার সর্বোত্তম উপায় কী?

আমি এই সমাধানটি এখানে পেয়েছি :

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

তবে পোস্টগ্রাগের সাথে এটি কাজ করছে বলে মনে হয় না। আমি এই ত্রুটি পাচ্ছি:

পিজি :: গ্রুপিংএরার: এআরআরআর: কলাম "পার্টস.আইডি" অবশ্যই গ্রুপ বা গ্রুপে উপস্থিত থাকতে হবে বা একটি সামগ্রিক ফাংশনে ব্যবহৃত হবে


3
নিয়মিত এসকিউএল-তে আমি একটি স্ব-যোগদান ব্যবহার করতাম, এরকম কিছু select a.id, b.id, name, email FROM user a INNER JOIN user b USING (name, email) WHERE a.id > b.id। অ্যাক্টিভেকর্ড-স্পকে কীভাবে তা প্রকাশ করা যায় সে সম্পর্কে কোনও ধারণা নেই।
ক্রেগ রিঞ্জার

উত্তর:


221

পরীক্ষিত ও কার্যকারী সংস্করণ

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
Magne

1
আপনি User.select ([: প্রথম,: ইমেল]) চেষ্টা করতে পারেন গ্রুপ (: প্রথম,: ইমেইল) .having ( "গণনা (*)> 1")
Serhii Nadolynskyi

3
আমি একই পদ্ধতিতে চেষ্টা করছি তবে ব্যবহারকারী.আইডিরও চেষ্টা করছি, এটি নির্বাচন করে যোগ করুন এবং গোষ্ঠী একটি খালি অ্যারে প্রদান করবে। আমি কীভাবে পুরো ব্যবহারকারীর মডেলটি ফিরিয়ে আনব, বা অন্তত: আইডি অন্তর্ভুক্ত করব?
অ্যাশবারি

5
.sizeপরিবর্তে ব্যবহার করুন.count
চার্লস হামেল

32

এই ত্রুটিটি ঘটে কারণ পোস্টগ্রিসের জন্য আপনার নির্বাচন বিভাগে গ্রুপিং কলাম স্থাপন করা দরকার।

চেষ্টা করে দেখুন:

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))

এটি সারিগুলিকে ফিরিয়ে দেবে যেখানে সারিটির ইমেল ঠিকানাটি অনন্য নয়।

আমি একাধিক বৈশিষ্ট্যের মাধ্যমে এটি করার কোনও উপায় সম্পর্কে অবগত নই।


। `` ইউজার.হোইয়ার (ইমেল: ইউজার.সलेक्ट (: ইমেল) .গ্রুপ (: ইমেল)। শেভিং ("গণনা (*)> 1")) `` `
চেট কোরি

আপনাকে ধন্যবাদ যে দুর্দান্ত কাজ করেছে :) এছাড়াও মনে হয় এটি শেষটি .select(:email)অনর্থক। আমি মনে করি এটি একটু পরিষ্কার, তবে আমি ভুল হতে পারি। User.where(email: User.select(:email).group(:email).having("count(*) > 1"))
চেট কোরি

2

আপনি যদি পোস্টগ্রিজ এসকিউএল ব্যবহার করেন তবে একক ক্যোয়ারির সাথে সমস্ত নকল পান :

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

-1

@ নতুন ব্যবহারকারীর নাম দ্বারা উপরের উত্তরের উপর ভিত্তি করে এখানে আমি বিশ্বাস করি প্রত্যেকটির জন্য গণনা দেখানোর সঠিক উপায়

res = User.select('first, email, count(1)').group(:first,:email).having('count(1) > 1')

res.each {|r| puts r.attributes } ; nil
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.