ALL operator in WHERE clause in Rails

社会主义新天地 提交于 2019-12-11 02:07:29

问题


The association is as shown below.

InstructorStudent has_many :fees

Fee belongs_to :instructor_student

I want to get the instructor student who has monthly detail in all given array. If monthly details is not present in any one of them then it should not return any record.

due_month = ["2017-01-01","2017-02-01",,"2017-03-01"]

Following is the query which I tried, I want to get InstructorStudent which belongs to all given three due_month, if any month have no data then it should return nil:

@fee_paid = 
InstructorStudent.first.joins(:fees).where("fees.monthly_detail = 
ALL(ARRAY[?]::date[]) AND fees.course_type = ?", due_month.map{|i| i 
},"per month");

Edit 1:

@erwin-brandstetter here is my final query

InstructorStudent.where("
  instructor_students.Id IN (?)",Instructor.find(17).per_month_active_student
).joins(
  "INNER JOIN fees ON fees.instructor_student_id = instructor_students.id LEFT OUTER JOIN fee_payment_notifications ON fee_payment_notifications.fee_id = fees.id"
).where(
  "fee_payment_notifications.status <> ? AND
  fees.monthly_detail = ANY(ARRAY[?]::date[]) AND
  fees.course_type = ? AND
  fees.payment_status <> ?"
  , 'Paid',dueMonth,"per month", "Due"
).group(
  'fees.instructor_student_id'
).
having(
  'count(*) = ?', dueMonth.length
)

Associations:

InstructorStudent has_many Fees
Fee belongs_to instructor_student

Fee has_many fee_payment_notifications
FeePaymentNotifications belongs to fee

Here What I do for fetching instructor students. which has fees.monthly_detail present in array of dueMonth and fees.payment_status is "Due" and Fees.course_type is "per month" and fee_payment_notifications should not be "Paid".

It is not compulsory that there is always fee_payment_notifications is present. So, If fee has fee_payment_notifications than only it should check for its status. If there is no any fee_payment_notifications than record should be fetched. If there is any fee_payment_notifications and status is "Paid" than record should not be fetched.


回答1:


That's a case of relational-division.

Actual table definitions (standard 1:n relationship, hidden by the Ruby ORM) will be something like this:

CREATE TABLE instructor_student (
   id serial PRIMARY KEY
   name ...
);

CREATE TABLE fees (
   id serial PRIMARY KEY
 , instructor_student_id integer NOT NULL REFERENCES instructor_student
 , course_type ...
 , monthly_detail date
 , UNIQUE (instructor_student_id, course_type, monthly_detail)
);

Your attempt at a query effectively tries to test each single row in fees against multiple values in the given array, which always fails while elements of the array are not identical. One value cannot be the same as multiple other values. You need a different approach:

SELECT instructor_student_id
FROM   fees
WHERE  course_type = ?
AND    monthly_detail = ANY(ARRAY[?]::date[])  -- ANY, not ALL!
GROUP  BY instructor_student_id
HAVING count(*) = cardinality(ARRAY[?]::date[]);

This is assuming distinct values in your array and unique entries in your table fees like enforced by the UNIQUE constraint I added above. Else, counts are not reliable and you have to use a more sophisticated query. Here is an arsenal of options:

  • How to filter SQL results in a has-many-through relation

As you can see, I did not involve the table instructor_student at all. While referential integrity is enforced with a FK constraint (like it typically is), we can work with fees alone to determine qualifying instructor_student_id. If you need to fetch more attributes from the main table, do that in a 2nd step, like:

SELECT i.*  -- or whatever you need
FROM   instructor_student i
JOIN  (
   SELECT ...  -- query from above
   ) f ON f.instructor_student_id = i.id
;



回答2:


You could just convert the months to Ruby's Date class and let ActiveRecord do the work:

due_month= ["2017-01-01","2017-02-01","2017-03-01"]    
fee_paid = InstructorStudent.joins(:fees).where("fees.monthly_detail" => due_month.map{|month| Date.parse month}, "fees.course_type" => "per month")


来源:https://stackoverflow.com/questions/44816759/all-operator-in-where-clause-in-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!