我在mysql中创建了我想要的确切查询,工作正常:
SELECT
tasks.*
FROM
tasks
INNER JOIN
leads
ON leads.id = tasks.taskable_id AND tasks.taskable_type = "Lead"
WHERE
tasks.taskable_id IN (1, 2)
AND
(
tasks.id =
(
SELECT tasks.id
FROM tasks
WHERE tasks.taskable_id = leads.id
AND
tasks.taskable_type = "Lead"
AND
appointment_status = 1
ORDER BY created_at asc
LIMIT 1
)
)
我花了两个多小时尝试将其翻译成ActiveRecord语法,但我无法让它工作。我得到的最接近的是:
Task.joins(:lead_tasks)
.where(
taskable_id: self.all.map(&:id)
)
.where(
"tasks.id = (?)",
Task.select(:id)
.where("tasks.taskable_id = (?) AND tasks.taskable_type = ?", self.where(appointment_status: APPOINTMENT_STATUS[:yes]).map(&:id), "Lead")
.order('created_at asc')
.limit(1)
)
class Task
belongs_to :lead_tasks, -> { where(tasks: { taskable_type: "Lead"}) },foreign_key: :taskable_id, class_name: "Lead"
但这会生成如下所示的SQL:
SELECT `tasks`.* FROM `tasks`
INNER JOIN `leads` ON `leads`.`id` = `tasks`.`taskable_id`
AND
`tasks`.`taskable_type` = 'Lead'
WHERE `tasks`.`taskable_id` IN (1, 2)
AND
(tasks.id = (SELECT `tasks`.`id` FROM `tasks` WHERE (tasks.taskable_id = (1,2)
AND tasks.taskable_type = 'Lead') ORDER BY created_at asc LIMIT 1));
区别在于Rails在WHERE之后添加了extra()导致以下语法错误:
Mysql2::Error: Operand should contain 1 column(s)
如何强制Rails不添加()?或者更好的是,在Rails中构建这个子查询的正确方法是什么?
答案 0 :(得分:0)
我得到了这样的工作:
sql = Task.select(:id).where("tasks.taskable_id = leads.id AND tasks.taskable_type = 'Lead' AND appointment_status = 1").order("created_at asc").limit(1).to_sql
Task.joins(:lead_tasks).where(taskable_id: self.all.map(&:id)).where("tasks.id = (#{sql})")
这将返回我需要的任务对象的ActiveRecord关系。