如何将多个 table 与多个 where 连接起来
How to join multiple table with multiple where
我的目的是获取所有与 school_admin
或 dormitory_admin
有关系的用户
所以这是 tables。
users (has one school_admin or has one dormitory_admin)
-id
-username
has_one :school_admin
has_one :dormitory_admin
school_admins (pivot table)
-id
-school_id
-user_id
belongs_to :user
belongs_to :school
dormitory_admins (pivot table)
-id
-dormitory_id
-user_id
school (has many dormitory)
-id
-name
has_many :dormitories
dormitory (belongs to one school)
-id
-school_id
这是我当前的查询(我现在有 2 个查询,我需要将它们合并为一个查询)
@q1 = User.joins(:school_admin).where(school_admin: { school_id: current_user.school_admin.school_id }).select("users.id, users.username, school_admin.name, school_admin.phone").ransack(params[:q])
@q2 = User.joins(:dormitory_admin).where(dormitory_admin: { dormitory_id: current_user.school_admin.school.dormitories.pluck(:id) }).select("users.id, users.username, dormitory_admin.name, dormitory_admin.phone").ransack(params[:q])
我正在使用 ransack gem 进行 table 过滤,并使用 PostgreSQL 进行数据库处理。
我可以像 ActiveRecord::Base.connection.execute(sql)
一样使用纯 SQL 来执行“UNION”,但是如果我使用它,搜查 gem 将不起作用。
您可以在现有范围上使用 to_sql,然后将其粘贴到 from 子句中
query1 = User.joins(:school_admin).where(school_admin: current_user.school_admin).select("users.id, users.username, school_admins.name, school_admins.phone")
query2 = User.joins(:dormitory_admin).where(dormitory_admin: current_user.dormitory_admin).select("users.id, users.username, dormitory_admins.name, dormitory_admins.phone")
User.from("(#{query1.to_sql} UNION #{query2.to_sql}) AS users").ransack(params[:q])
SELECT "users".* FROM (
SELECT
users.id,
users.username,
school_admins.name,
school_admins.phone
FROM "users"
INNER JOIN "school_admins"
ON "school_admins"."user_id" = "users"."id"
WHERE "users"."id" = 1
UNION
SELECT
users.id,
users.username,
dormitory_admins.name,
dormitory_admins.phone
FROM "users"
INNER JOIN "dormitory_admins"
ON "dormitory_admins"."user_id" = "users"."id"
WHERE "users"."id" = 2)
AS users;
或者更好的方法是避免重复查询
User.from("(#{User.joins(:school_admin).where(school_admin: current_user.school_admin).select("users.id, users.username, school_admins.name, school_admins.phone").to_sql} UNION #{User.joins(:dormitory_admin).where(dormitory_admin: current_user.dormitory_admin).select("users.id, users.username, dormitory_admins.name, dormitory_admins.phone").to_sql}) AS users").ransack(params[:q])
注:我用的table名字是复数school_admins& dormitory_admins。另外,我修改了 query1 & query2
中的 where 子句
我的目的是获取所有与 school_admin
或 dormitory_admin
所以这是 tables。
users (has one school_admin or has one dormitory_admin)
-id
-username
has_one :school_admin
has_one :dormitory_admin
school_admins (pivot table)
-id
-school_id
-user_id
belongs_to :user
belongs_to :school
dormitory_admins (pivot table)
-id
-dormitory_id
-user_id
school (has many dormitory)
-id
-name
has_many :dormitories
dormitory (belongs to one school)
-id
-school_id
这是我当前的查询(我现在有 2 个查询,我需要将它们合并为一个查询)
@q1 = User.joins(:school_admin).where(school_admin: { school_id: current_user.school_admin.school_id }).select("users.id, users.username, school_admin.name, school_admin.phone").ransack(params[:q])
@q2 = User.joins(:dormitory_admin).where(dormitory_admin: { dormitory_id: current_user.school_admin.school.dormitories.pluck(:id) }).select("users.id, users.username, dormitory_admin.name, dormitory_admin.phone").ransack(params[:q])
我正在使用 ransack gem 进行 table 过滤,并使用 PostgreSQL 进行数据库处理。
我可以像 ActiveRecord::Base.connection.execute(sql)
一样使用纯 SQL 来执行“UNION”,但是如果我使用它,搜查 gem 将不起作用。
您可以在现有范围上使用 to_sql,然后将其粘贴到 from 子句中
query1 = User.joins(:school_admin).where(school_admin: current_user.school_admin).select("users.id, users.username, school_admins.name, school_admins.phone")
query2 = User.joins(:dormitory_admin).where(dormitory_admin: current_user.dormitory_admin).select("users.id, users.username, dormitory_admins.name, dormitory_admins.phone")
User.from("(#{query1.to_sql} UNION #{query2.to_sql}) AS users").ransack(params[:q])
SELECT "users".* FROM (
SELECT
users.id,
users.username,
school_admins.name,
school_admins.phone
FROM "users"
INNER JOIN "school_admins"
ON "school_admins"."user_id" = "users"."id"
WHERE "users"."id" = 1
UNION
SELECT
users.id,
users.username,
dormitory_admins.name,
dormitory_admins.phone
FROM "users"
INNER JOIN "dormitory_admins"
ON "dormitory_admins"."user_id" = "users"."id"
WHERE "users"."id" = 2)
AS users;
或者更好的方法是避免重复查询
User.from("(#{User.joins(:school_admin).where(school_admin: current_user.school_admin).select("users.id, users.username, school_admins.name, school_admins.phone").to_sql} UNION #{User.joins(:dormitory_admin).where(dormitory_admin: current_user.dormitory_admin).select("users.id, users.username, dormitory_admins.name, dormitory_admins.phone").to_sql}) AS users").ransack(params[:q])
注:我用的table名字是复数school_admins& dormitory_admins。另外,我修改了 query1 & query2
中的 where 子句