【问题标题】:Activerecord Left Outer Join not working with NOT conditionActiverecord 左外连接不适用于 NOT 条件
【发布时间】:2016-01-15 15:51:47
【问题描述】:

此查询有效:

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 文档中没有发现任何内容表明这是不可能的 - 我在这里遗漏了一些基本的东西吗?

【问题讨论】:

    标签: mysql ruby-on-rails ruby-on-rails-4 activerecord


    【解决方案1】:

    可能每个帖子都出现在该联接表中某处,其中联接表中的行具有 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 连接的 foo。

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

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

    这给你 1,2,3 的 foos.ids。

    如果你然后说“给我不同的 foos.id where bar.id 5”,你可能会直觉地认为你会得到完整的 foo id 减去你从上一个查询中得到的那些,即[]。您认为您在问“给我未加入第 5 条的 foos”。但是你得到的是这些行:

    1       qux       6       bax
    2       qaz       6       bax
    

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

    换句话说,您想获得“未加入类别 20 的帖子”,但您实际要求的是“加入到没有 id 20 的类别的帖子”。这在逻辑上略有不同。

    【讨论】:

      【解决方案2】:

      同意马克斯。我会像这样构造这个条件:

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

      相反,只是因为这样你就不会在连接表数学中纠缠不清。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-05
        • 2020-10-12
        • 2015-01-07
        • 1970-01-01
        • 1970-01-01
        • 2015-05-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多