繁体   English   中英

Activerecord Left Outer Join不使用NOT条件

[英]Activerecord Left Outer Join not working with NOT condition

此查询有效:

person.posts.includes(:categories).
references(:categories).where(categories: { id: 20 })

但是在NOT条件下:

person.posts.includes(:categories).
references(:categories).where.not(categories: { id: 20 })

第二个查询完成没有错误 - 但没有对结果进行过滤 - 因此它返回所有帖子。

MySQL:

SELECT COUNT(DISTINCT `posts`.`id`) FROM `posts` 
LEFT OUTER JOIN `category_manifests` ON `category_manifests`.`post_id` = `posts`.`id` 
LEFT OUTER JOIN `categories` ON `categories`.`id` = `category_manifests`.`category_id` 
WHERE `posts`.`person_id` = 14 AND (`categories`.`id` != 20)

我没有在Activerecord文档中找到任何建议,这是不可能的 - 我在这里遗漏了一些基本的东西吗?

可能是每个帖子都出现在该连接表中其中连接表中的行具有categories.id <> 20.连接表最终看起来像这样:

foos.id foos.name bars.id bars.name
1       qux       5       bux
2       qaz       5       bux
1       qux       6       bax
2       qaz       6       bax
3       qiz       5       bux

假设您想要与条形图5连接的foos。

如果你说,对于这个示例表,给我不同的foos.id,其中bars.id = 5你会得到这些行:

1       qux       5       bux
2       qaz       5       bux
3       qiz       5       bux 

它给你foos.ids 1,2,3。

如果你然后说“给我不同的foos.id where bars.id <> 5”,你可能会直觉地认为你得到的全套foo id减去你从前一个查询得到的那些,即[]。 你认为你在问“给我没有加入5号栏的foos”。 但你得到的是这些行:

1       qux       6       bax
2       qaz       6       bax

因为这些是bars.id <> 5的行,而这些行的foos.ids是[1,2]。 这似乎与您的情况类似。

换句话说,您希望“帖子未加入第20类”,但您实际要求的是“加入到没有ID 20的类别的帖子”。 从逻辑上讲,这略有不同。

同意Max。 我会像这样构造这种情况:

.where("NOT EXISTS (
  SELECT * FROM category_manifests 
  WHERE post_id = posts.id AND category_id = ?)", 
    excluded_category.id) 

相反,只是因为这种方式你不能在连接表数学中纠缠不清。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM