Mar*_*arc 9 sql postgresql ruby-on-rails
我有一个范围来限制所有questions用户是否投票.在模型中:
scope :answered_by, lambda {|u| joins(:votes).where("votes.user_id = ?", u.id) }
scope :unanswered_by, lambda {|u| joins(:votes).where("votes.user_id != ?", u.id) }
Run Code Online (Sandbox Code Playgroud)
在控制器中,我这样称呼它们:
@answered = Question.answered_by(current_user)
@unanswered = Question.unanswered_by(current_user)
Run Code Online (Sandbox Code Playgroud)
unanswered_by范围不正确.我基本上想找到没有投票的地方.相反,它试图寻找是否存在与当前用户不相等的投票.任何想法如何返回不存在连接的所有记录?
Erw*_*ter 17
使用EXISTS反半连接:
WHERE NOT EXISTS (
SELECT 1
FROM votes v
WHERE v.some_id = base_table.some_id
AND v.user_id = ?
)
Run Code Online (Sandbox Code Playgroud)
... NOT EXISTS()(e)和NOT IN()(i)之间是双重的:
性能
(e)通常更快.一旦找到第一个匹配的行,它就可以停止扫描表或索引.(i)也可以由查询规划器进行优化,但程度较小,因为NULL处理更复杂.
正确性
如果子查询表达式中的结果值之一可以是NULL,则(i)的结果可能是NULL您期望的结果 - 并且(e)将返回 - TRUE.手册:
如果所有每行结果不等或为null,并且至少有一个null,则结果
NOT IN为null.
从本质上讲,(NOT) EXISTS在大多数情况下是更好的选择.
您的查询可能如下所示:
SELECT *
FROM questions q
WHERE NOT EXISTS (
SELECT 1
FROM votes v
WHERE v.question_id = q.id
AND v.user_id = ?
)
Run Code Online (Sandbox Code Playgroud)
千万不能加入到votes在基本查询.这将使努力无效.
此外NOT EXISTS并且NOT IN也有LEFT JOIN / IS NULL.此相关答案中的更多语法变体:
| 归档时间: |
|
| 查看次数: |
9881 次 |
| 最近记录: |