admin

Rails中WHERE子句中的ALL运算符

sql

关联如下所示。

InstructorStudent has_many :fees

Fee belongs_to :instructor_student

我想得到在所有给定数组中都有每月详细信息的指导学生。如果其中任何一个都不包含每月详细信息,则它不应返回任何记录。

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

以下是我尝试过的查询,我想获得InstructorStudent属于所有给定三个Due_month的查询,如果任何月份没有数据,则应返回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");

编辑1:

@ erwin-brandstetter这是我的最终查询

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
)

关联:

InstructorStudent has_many Fees
Fee belongs_to instructor_student

Fee has_many fee_payment_notifications
FeePaymentNotifications belongs to fee

在这里,我为吸引指导生做些什么。在dueMonth数组中包含fee.monthly_detail的内容,并且fee.payment_status为“到期”,而Fees.course_type为“每月”,并且fee_payment_notifications不应为“已付费”。

不一定总要有fee_payment_notifications。
因此,如果fee具有fee_payment_notifications,则仅应检查其状态。如果没有任何fee_payment_notifications,则应提取记录。如果有任何fee_payment_notifications且状态为“已付费”,则不应获取记录。


阅读 228

收藏
2021-07-01

共1个答案

admin

这是关系部门的一种情况。

实际的表定义(标准的1:n关系,由Ruby ORM隐藏)如下所示:

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

您对查询的尝试有效地尝试fees针对给定数组中的多个值测试每一行,当数组中的元素不相同时,这 总是会 失败。 一个 值不能与 多个
其他值相同。您需要一种不同的方法:

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[]);

假设您的数组中有 不同的
值,并且表中的费用是唯一的条目,就像UNIQUE我上面添加的约束所强制执行的那样。否则,计数是不可靠的,您必须使用更复杂的查询。这是一个选项库:

如您所见,我根本没有涉及该表instructor_student。虽然参照完整性是通过FK约束来强制执行的(通常如此),但我们可以fees单独使用它来确定资格instructor_student_id。如果您需要从主表中获取更多属性,请在第二步中进行操作,例如:

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