Arel table 关系除法
Arel table relational division
我正在使用 Rails 5.1 和 PostgreSQL 9.5,我是 Arel 表的新手。我正在尝试创建一个查询(我希望最终与其他范围查询链接),其中 returns 记录所有相关记录与给定输入匹配的位置。
给定数组 weekday_ids: [1, 2, 5, 6]
,只有 return ranges
具有活动 time_slots
匹配 all 给定 weekday_ids
型号
class Range < ApplicationRecord
has_many :time_slots
end
class TimeSlot < ApplicationRecord
belongs_to :range
belongs_to :weekday
end
return预期结果
的工作示例
def self.qualified_time_slots(weekday_ids = nil)
weekday_ids ||= [1, 2, 5, 6]
qualified_ranges = Range.includes(:time_slots).all.map do |range|
active_time_slots = range.time_slots.where(active: true)
range if weekday_ids.all? { |day| active_time_slots.map(&:weekday_id).include? day }
end
# return
qualified_ranges.compact
end
当前无法通过 Arel Query 尝试实现与上述方法相同的方法
Range.joins(
:time_slots
).where(
time_slots: { active: true }
).where(
TimeSlot.arel_table[:weekday_id].in(weekday_ids)
)
预期结果
# Should return:
[
range: {
id: 1,
time_slots: [
{ weekday_id: 1 },
{ weekday_id: 2 },
{ weekday_id: 5 },
{ weekday_id: 6 },
]
},
range: {
id: 2,
time_slots: [
{ weekday_id: 0 },
{ weekday_id: 1 },
{ weekday_id: 2 },
{ weekday_id: 3 },
{ weekday_id: 4 },
{ weekday_id: 5 },
{ weekday_id: 6 },
]
}
]
# Should NOT return
[
range: {
id: 3,
time_slots: [
{ weekday_id: 1 },
{ weekday_id: 2 },
{ weekday_id: 5 },
]
},
range: {
id: 4,
time_slots: [
{ weekday_id: 0 },
{ weekday_id: 6 },
]
}
]
EDIT - 在此过程中,我遵循了 Joe Celko article on Relational Division 中的示例并创建了此原始 SQL 查询,该查询似乎有效, 但尚未完全测试:
ActiveRecord::Base.connection.exec_query("
SELECT
ts.range_id
FROM
time_slots AS ts
WHERE
ts.active = true
AND
ts.weekday_id IN (#{weekday_ids.join(',')})
GROUP BY
ts.range_id
HAVING COUNT(weekday_id) >= #{weekday_ids.length};
")
我仍在对此进行测试,但看起来它正在运行:
Range.joins(
:time_slots
).where(
TimeSlot.arel_table[:active].eq(
true
).and(
TimeSlot.arel_table[:weekday_id].in(
weekday_ids
)
)
).group(
Range.arel_table[:id]
).having(
TimeSlot.arel_table[:weekday_id].count(true).gteq(weekday_ids.count)
)
我正在使用 Rails 5.1 和 PostgreSQL 9.5,我是 Arel 表的新手。我正在尝试创建一个查询(我希望最终与其他范围查询链接),其中 returns 记录所有相关记录与给定输入匹配的位置。
给定数组 weekday_ids: [1, 2, 5, 6]
,只有 return ranges
具有活动 time_slots
匹配 all 给定 weekday_ids
型号
class Range < ApplicationRecord
has_many :time_slots
end
class TimeSlot < ApplicationRecord
belongs_to :range
belongs_to :weekday
end
return预期结果
的工作示例def self.qualified_time_slots(weekday_ids = nil)
weekday_ids ||= [1, 2, 5, 6]
qualified_ranges = Range.includes(:time_slots).all.map do |range|
active_time_slots = range.time_slots.where(active: true)
range if weekday_ids.all? { |day| active_time_slots.map(&:weekday_id).include? day }
end
# return
qualified_ranges.compact
end
当前无法通过 Arel Query 尝试实现与上述方法相同的方法
Range.joins(
:time_slots
).where(
time_slots: { active: true }
).where(
TimeSlot.arel_table[:weekday_id].in(weekday_ids)
)
预期结果
# Should return:
[
range: {
id: 1,
time_slots: [
{ weekday_id: 1 },
{ weekday_id: 2 },
{ weekday_id: 5 },
{ weekday_id: 6 },
]
},
range: {
id: 2,
time_slots: [
{ weekday_id: 0 },
{ weekday_id: 1 },
{ weekday_id: 2 },
{ weekday_id: 3 },
{ weekday_id: 4 },
{ weekday_id: 5 },
{ weekday_id: 6 },
]
}
]
# Should NOT return
[
range: {
id: 3,
time_slots: [
{ weekday_id: 1 },
{ weekday_id: 2 },
{ weekday_id: 5 },
]
},
range: {
id: 4,
time_slots: [
{ weekday_id: 0 },
{ weekday_id: 6 },
]
}
]
EDIT - 在此过程中,我遵循了 Joe Celko article on Relational Division 中的示例并创建了此原始 SQL 查询,该查询似乎有效, 但尚未完全测试:
ActiveRecord::Base.connection.exec_query("
SELECT
ts.range_id
FROM
time_slots AS ts
WHERE
ts.active = true
AND
ts.weekday_id IN (#{weekday_ids.join(',')})
GROUP BY
ts.range_id
HAVING COUNT(weekday_id) >= #{weekday_ids.length};
")
我仍在对此进行测试,但看起来它正在运行:
Range.joins(
:time_slots
).where(
TimeSlot.arel_table[:active].eq(
true
).and(
TimeSlot.arel_table[:weekday_id].in(
weekday_ids
)
)
).group(
Range.arel_table[:id]
).having(
TimeSlot.arel_table[:weekday_id].count(true).gteq(weekday_ids.count)
)