SQL 获取所有至少有5个符合条件的关联的记录

问题描述 投票:0回答:1

我对我正在尝试编写的查询有点迷失。正如问题所述,我试图从表中返回所有记录,该表至少有 5 个满足特定条件的关联记录。具体来说,我有汽车和司机。一个司机可以拥有很多辆车,我想返回所有在 3 周前创建的至少拥有 5 辆车的司机。

下面的查询为我提供了在过去 3 周内至少创建了一辆汽车的司机的 ID,但我无法弄清楚如何添加额外的计数步骤,以便我只返回至少拥有一辆汽车的司机的 ID 5!

SELECT DISTINCT d.id FROM drivers d
     JOIN cars c ON c.driver_id = d.id
     WHERE c.created_at >= NOW() - '3 weeks'::INTERVAL

我希望我能够做类似的事情(显然是伪代码)

SELECT DISTINCT d.id FROM drivers d
     JOIN cars c ON c.driver_id = d.id
     WHERE c.created_at >= NOW() - '3 weeks'::INTERVAL
     AND d.id IN (SELECT <driver ids which have more than 5 cars created in the last 3 weeks>)

但事实证明并没有这么简单。

我正在 Rails 中工作,但最终编写了原始查询。有什么建议吗?

sql ruby-on-rails postgresql
1个回答
0
投票

由于您使用的是 Postgres,因此您可以使用

GROUP BY
HAVING
,如下所示:

Driver
  .joins(:cars)
  .where(cars: {created_at: 3.weeks.ago..})
  .group(:id)
  .having(Arel.star.count.gt(4))

这将产生以下 SQL

SELECT 
  drivers.*
FROM 
  drivers
  INNER JOIN cars ON cars.driver_id = drivers.id 
WHERE 
  cars.created_at >= [3 weeks ago date] 
GROUP BY 
  drivers.id 
HAVING 
  COUNT(*) > 4 

为了与您当前的实现保持一致,或者对于不支持仅按主键分组的数据库,我们可以使用

Driver.where(id: 
  Car.select(:driver_id)
    .where(created_at: 3.weeks.ago..)
    .group(:driver_id)
    .having(Arel.star.count.gt(4))
)

这会产生

SELECT 
  drivers.*
FROM 
  drivers
WHERE 
  drivers.id IN ( 
    SELECT 
      cars.driver_id
    FROM
      cars
    WHERE 
     cars.created_at >= [3 weeks ago date] 
    GROUP BY 
      cars.driver_id
    HAVING 
      COUNT(*) > 4 
)
© www.soinside.com 2019 - 2024. All rights reserved.