【问题标题】:Rails 5 - ActiveRecord - Filtering has_many relation with includes and not exclude empty valuesRails 5 - ActiveRecord - 过滤包含而不排除空值的 has_many 关系
【发布时间】:2017-10-19 14:05:38
【问题描述】:

让我解释一下标题。

我的模型 A 有多个模型 B。

我想在显示所有模型 A 的同时按日期的月份和年份过滤模型 B

例如:

A1 -> 3 Bs

A2 -> 0 Bs

A3 -> 1 B

这是我现在的查询:

A.includes(:b_relation)
 .where("extract(month from b.date) = #{month}").references(:b_relation)
 .where("extract(year from b.date) = #{year}").references(:b_relation)
 .all

有效!但它只给了我至少有一个 B 的 A。没有任何 B 的 A 不显示。

如何使查询包含没有任何 B 的模型 A?

【问题讨论】:

    标签: sql ruby-on-rails postgresql activerecord eager-loading


    【解决方案1】:

    您现在正在执行的查询使用INNER JOIN,它将排除A 中没有关联Bs 的记录。你想要的是一个LEFT OUTER JOIN——又名LEFT JOIN。左连接包括父表中的所有行,无论关联表中是否有任何关联记录。

    我总是发现这张图片对于可视化 SQL 连接类型很有用:

    Rails 5 对此有一个 left_outer_joins method(别名:left_joins):

    A.left_outer_joins(:b_relation)
    

    在早期版本的 Rails 中,它更手动(我只是在此处编造表名):

    A.joins('LEFT OUTER JOIN "bs" ON "bs"."a_id" = "as"."id"')
    

    【讨论】:

    • 如果我查看执行的查询,它确实会执行 LEFT OUTER JOIN,因为内部包含将决定使用 'eager_load' ActiveRecord 方法。它已经使用了 LEFT OUTER JOIN
    • 您能分享一下您的 AR 查询生成的 SQL 吗?
    • 类似这样的 SELECT "A"."id" AS t0_r0, -- A COLUMNS "B"."id" AS t1_r0, -- B COLUMNS FROM "A" LEFT OUTER JOIN "B" ON "B"."a_id" = "A"."id" WHERE "A"."deleted_at" 为 NULL AND "A"."blabla_id" = 'cfa7e8a8-5566-4ce7-bcbc-05cf420cf7d1' AND ((Extract (month FROM B.date) = 10) AND (Extract(year FROM B.date) = 2017) OR B.date IS NULL)
    猜你喜欢
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    相关资源
    最近更新 更多