[英]Query for Records beginning with “The” and move “The” the end of a string and join with a comma in Rails Postgres
[英]Rails Postgres query to exclude any results that contain one of three records on join
这是一个很难描述的问题,但是我在联接另一个表的地方有Rails查询,并且想排除联接表包含以下三个条件之一的任何结果。
我有一个与CarUserRole
模型/记录相关的Device
模型。 在该CarUserRole记录中,它将包含三个:role
role-“所有者”,“监视器”,“驱动程序”之一。 我想在没有相关的CarUserRole记录的情况下返回任何结果,其中role: "owner"
。 我该怎么做?
这是我的第一次尝试-
Device.joins(:car_user_roles).where('car_user_roles.role = ? OR car_user_roles.role = ? AND car_user_roles.role != ?', 'monitor', 'driver', 'owner')
这是SQL-
"SELECT \"cars\".* FROM \"cars\" INNER JOIN \"car_user_roles\" ON \"car_user_roles\".\"car_id\" = \"cars\".\"id\" WHERE (car_user_roles.role = 'monitor' OR car_user_roles.role = 'driver' AND car_user_roles.role != 'owner')"
更新
我应该提到一台设备有时具有多个CarUserRole记录。 设备可以具有“所有者”和“驱动程序” CarUserRole。 我还要注意,他们只能有一个所有者。
Anwser
我最终通过聊天使用了@Reub的解决方案-
where(CarUserRole.where("car_user_roles.car_id = cars.id").where(role: 'owner').exists.not)
由于car_user_roles表可以有多个具有相同car_id的记录,因此内部联接可能导致联接表对cars表中的每一行都具有多行。 因此,对于在car_user_roles表中具有3条记录(监视,所有者和驾驶员)的汽车,联接表中将有3条记录(每个记录具有不同的作用)。 您的查询将过滤出角色为所有者的行,但它将与其他两个匹配,即使该查询具有记录为“所有者”的汽车,也会由于查询而返回该汽车。
首先让我们尝试为所需的结果形成一个sql查询。 然后,我们可以将其转换为Rails查询。
SELECT * FROM cars WHERE NOT EXISTS (SELECT id FROM car_user_roles WHERE role='owner' AND car_id = cars.id);
如果您想要没有角色为“所有者”的car_user_role的设备,则以上内容就足够了。 但这也可以为您提供在car_user_roles中没有相应记录的设备。 如果要确保设备在car_user_roles中至少有一条记录,可以将以下内容添加到上述查询中。
AND EXISTS (SELECT id FROM car_user_roles WHERE role IN ('monitor', 'driver') AND car_id = cars.id);
现在,我们需要将其转换为Rails查询。
Device.where(
CarUserRole.where("car_user_roles.car_id = cars.id").where(role: 'owner').exists.not
).where(
CarUserRole.where("car_user_roles.car_id = cars.id").where(role: ['monitor', 'driver']).exists
).all
如果您的Rails版本支持exists?
您也可以尝试以下方法exists?
:
Device.joins(:car_user_roles).exists?(role: ['monitor', 'driver']).exists?(role: 'owner').not.select('cars.*').distinct
选择不同的汽车
SELECT DISTINCT (cars.*) FROM cars
使用LEFT JOIN拉入car_user_roles
LEFT JOIN car_user_roles ON cars.id = car_user_roles.car_id
仅选择不包含“所有者” car_user_role的汽车
WHERE NOT EXISTS(SELECT NULL FROM car_user_roles WHERE cars.id = car_user_roles.car_id AND car_user_roles.role = 'owner')
仅选择包含“驾驶员”或“监视器”的汽车car_user_role
AND (car_user_roles.role IN ('driver','monitor'))
放在一起:
SELECT DISTINCT (cars.*) FROM cars LEFT JOIN car_user_roles ON cars.id = car_user_roles.car_id WHERE NOT EXISTS(SELECT NULL FROM car_user_roles WHERE cars.id = car_user_roles.car_id AND car_user_roles.role = 'owner') AND (car_user_roles.role IN ('driver','monitor'));
编辑:
直接从Rails执行查询,仅返回找到的对象ID
ActiveRecord::Base.connection.execute(sql).collect { |x| x['id'] }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.