【问题标题】:Find parent record with no child with certain param certain parameters使用某些参数查找没有子项的父记录
【发布时间】:2019-09-25 18:59:20
【问题描述】:

所以我知道如何找到所有没有子记录的父记录。

Parent.joins(:child).where(child: {id: nil})

但是,如何查找过去 30 天内没有创建子项的所有父记录。我尝试了以下方法,但没有成功

Parent.joins(:child).where(child: {id: nil, created_at: 30.days.ago...Time.current})
Parent.joins(:child).where(child: {created_at: 30.days.ago...Time.current).where(child: {id: nil})

他们都没有工作。有什么想法吗?

【问题讨论】:

  • 您是指过去 30 天内创建的所有父记录,还是所有父记录?
  • 一个好问题@SebastianPalma,我注意到我们已经沿着不同的路线走了:)
  • 所有父记录
  • 第一次查询不行

标签: sql ruby-on-rails postgresql activerecord


【解决方案1】:

您应该可以为此使用where.not

更新:即使没有孩子也要获取所有记录,请使用left_outer_joins

# from: 
# Parent.joins(:child).where.not(child: { created_at: 30.days.ago...Time.current } )
# to:
Parent.left_outer_joins(:child).where.not(child: { created_at: 30.days.ago...Time.current } )

这很不言自明,绘制了所有符合条件的记录。

为了解释joinsleft_outer_joins 之间的区别,我将引用another question 的一句话,因为他们的解释很完美:

INNER JOIN:当两个表都匹配时返回行。

LEFT JOIN:返回左表中的所有行,即使右表中没有匹配项。

因此您需要后者以便包含没有子项的父记录。

希望对您有所帮助 - 如果您有任何问题,请告诉我:)

【讨论】:

  • @engineersmnky 如果根本没有子记录,我仍然希望查看父记录。我该怎么做?
  • @stevo999999 - 更新为使用left_outer_joins :)
  • @SRack 在连接表上有条件的外连接将创建一个内连接此外,如果我正确阅读了这个问题,这仍然是不正确的,因为在 30 天窗口之外创建的孩子的父母将会出现结果
【解决方案2】:

你需要内部查询来做你想做的事。一种方法:

Parent.where.not(id: Parent.joins(:child).where(child: { created_at: 30.days.ago...Time.current }).pluck(:id).uniq)

这将选择所有在 30 天内没有孩子的父母。希望对您有所帮助。

编辑:

它可以分为两个简单的查询:

unwanted_parents_ids = Parent.joins(:child).where(child: { created_at: 30.days.ago...Time.current }).pluck(:id).uniq
wanted_parents = Parent.where.not(id: unwanted_parents_ids)

【讨论】:

  • @SRack 不是那么复杂,您可以将其分成两个查询以便更容易理解,例如:不需要的父母身份 = Parent.joins(:child).where(child: { created_at: 30.days.ago. ..Time.current }).pluck(:id).uniq Wanted_pa​​rents = Parent.where.not(id: Wanted_pa​​rents_ids)
  • @SRack 不幸的是,我无法对您的答案发表评论,但实际上即使在添加 left_outer_joins 之后也不正确。因为如果父母在 30 天内创建了孩子,而在 30 天内创建了其他孩子,您的查询将获取此父母。我认为这不是作者想要的。他只想要在 30 天内没有孩子的父母。此查询的唯一解决方案是执行内部查询或在多个查询中中断它
  • @SRack 不正确。我不知道如何向你解释。我会尽力而为。我将为您举一个无效父级的示例,您的查询将获取它。想象一个有 2 个孩子的父母。 child_1 是在 30 天内创建的,child_2 不是在 30 天内创建的。当您执行 left_join 时,它不会将此父级与 child_1 一起加入,因为 child_1 是在 30 天内创建的。但是,它将与 child_2 一起加入父级,因为 child_2。它会将此父级作为不正确的有效父级返回。希望我解释清楚。
  • 请先试试我的例子,如果我错了再回来找我。 (这就是 JOIN 的工作原理)
  • 不要pluck ids select 他们。使用pluck 将创建一个Array,而使用select 将创建一个子查询,例如Parent.joins(:child).where(child: { created_at: 30.days.ago...Time.current }).select(:id).distinct。现在,当您调用 Parent.where.not(id: unwanted_parents_ids) 时,它将生成 id NOT IN ( SELECT parents.id FROM --...) 的 where 子句,而不是 id NOT IN (1,2,3,4 --...)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
  • 2017-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多