RIGHT OUTER JOIN使用WHERE返回空结果

时间:2016-06-29 20:18:16

标签: ruby-on-rails postgresql activerecord

我需要生成一份报告,说明特定用户在过去几个月每个月创建的所有记录(业务)。我提出了以下查询,并希望它为每个月提供一行。但是,这个用户在这几个月内没有创建任何记录(商家),所以我得到一个空的结果generate_series

我仍然期望每个月都能收到一行,因为我使用RIGHT OUTER JOIN选择了start = 3.months.ago stop = Time.now new_businesses = Business.select( "generate_series, count(id) as new"). joins("RIGHT OUTER JOIN ( SELECT generate_series(#{start.month}, #{stop.month})) series ON generate_series = date_part('month', created_at) "). where(created_at: start.beginning_of_month .. stop.end_of_month). where(author_id: creator.id). group("generate_series"). order('generate_series ASC') 列,但它并没有发生。

new_businesses = Business.select(
    "generate_series as month, count(id) as new").
  joins("RIGHT OUTER JOIN ( SELECT
    generate_series(#{start.month}, #{stop.month})) series
    ON (generate_series = date_part('month', created_at)
      AND author_id = #{creator.id}
      AND created_at BETWEEN '#{start.beginning_of_month.to_formatted_s(:db)}' AND
        '#{stop.end_of_month.to_formatted_s(:db)}'
    )
  ").
  group("generate_series").
  order('generate_series ASC')

如何更改查询以获取每个月的行而不是空结果?我正在使用PosgreSQL。

更新

此代码有效:

{{1}}

1 个答案:

答案 0 :(得分:2)

您的问题出现在where部分,这会破坏任何外部联接。考虑一下这个例子:

select *
from a right outer join b on (a.id = b.id)

它会返回b的所有行和a的关联值,但是:

select *
from a right outer join b on (a.id = b.id)
where a.some_field = 1

将删除a不存在的所有行。

进行此类演唱的正确方法是将过滤器放入join查询部分:

select *
from a right outer join b on (a.id = b.id and a.some_field = 1)

或使用子查询:

select *
from (select * from a where a.some_field = 1) as a right outer join b on (a.id = b.id)