rails中的嵌套sql查询:has_and_belongst_to_many

时间:2011-01-09 01:46:25

标签: sql ruby-on-rails arel

在我的应用程序中,我还没有用户完成的下一个任务。我有三个模型,A Book ,有很多任务,然后我有用户,它拥有并属于许多任务。表tasks_users表包含所有已完成的任务,因此我需要编写一个复杂的查询来查找要执行的下一个任务。

我在纯SQL中提出了两个有效的解决方案,但是我无法将它们转换为rails,这就是我需要帮助的地方

SELECT * FROM `tasks`
WHERE `tasks`.`book_id` = @book_id
AND `tasks`.`id` NOT IN (
    SELECT `tasks_users`.`task_id`
    FROM `tasks_users`
    WHERE `tasks_users`.`user_id` = @user_id)
ORDER BY `task`.`date` ASC
LIMIT 1;

同样没有嵌套选择

SELECT *
FROM tasks
LEFT JOIN tasks_users
    ON tasks_users.tasks_id = task.id
    AND tasks_users.user_id = @user_id
WHERE tasks_users.task_id IS NULL
AND tasks.book_id = @book_id
LIMIT 1;

这是我在使用MetaWhere插件的rails中所做的事情

book.tasks.joins(:users.outer).where(:users => {:id => nil})

但我无法弄清楚如何让当前用户在那里,

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

我认为这将使用LEFT JOIN复制第二个表单:

class Task < ActiveRecord::Base
  scope :next_task, lambda { |book,user| book.tasks.\
    joins("LEFT JOIN task_users ON task_users.task_id=tasks.id AND task_users.user_id=#{user.id}").\
    where(:tasks=>{:task_users=>{:task_id=>nil}}).\
    order("date DESC").limit(1) }
end

请注意,这不是tasks_users,而是使用表名task_user,这对于连接模型更为典型。此外,它需要调用:

Task.next_task(@book_id,@user_id)

答案 1 :(得分:0)

book.tasks.where("tasks.id not in (select task_id from tasks_users where user_id=?)", @user_id).first

这将为您提供第一个在当前用户的tasks_users中没有条目的任务。