mariadb 如何在MySQL中对JOIN表执行三重运算以使用OR操作数执行查询[特定情况]

whlutmcx  于 2022-11-08  发布在  Mysql
关注(0)|答案(3)|浏览(114)

亲爱的SO社区,您好!
我已经挣扎了一段时间了,因为时间不多了,我转向你。
我有这些表:

USERS:
user_id (PK)
user_name

PROJECTS:
project_id (PK)
project_name
user_id (FK) - referring to the creator of the project

用户和项目是M:N关系,该关系在表PERMISSIONS中捕获。

PERMISSIONS:
project_id (FK)
user_id (FK)

权限行包含单个用户和单个项目的访问规则。如果表中不存在给定用户和项目的对,则该用户无法访问该项目。
我试图查询当前用户应该有权访问的所有项目,即那些他创建的项目和那些在PERMISSIONS表中与他相关联的项目,但对于每个项目,我都希望得到其创建者的user_name。我在PHP中为一个预准备语句提供当前用户ID,该语句运行良好,但我似乎无法正确查询。我已经能够
我能够获得由某个用户创建或访问的项目,但我不知道如何加入USERS,以获得我查询的项目中user_id的user_name(项目创建者的用户名)。
我想问的是:

SELECT projects.name as name, projects.project_id as project_id, projects.user_id  as user_id, users.name as user_name
FROM projects JOIN permissions USING (project_id) JOIN users USING (user_id) WHERE permissions.user_id=:user_id OR 
projects.user_id=:user_id ORDER BY name
x6h2sr28

x6h2sr281#

有三种可能性:
1.在包含or的项目上使用join,以获取创建者和具有权限的创建者。通常不建议使用包含orjoin,因为这会导致表扫描。需要使用Distinct

select distinct u.user_name, p.project_name
from users u
left join permissions pm on pm.user_id = u.user_id
left join projects p on p.user_id = u.user_id or p.project_id = pm.project_id
where u.user_id = 2;
  1. Cross join projects,并且在where子句中有'or's。需要distinct
select distinct u.user_name, p.project_name
 from users u
 cross join projects p
 left join permissions pm on pm.user_id = u.user_id
 where u.user_id = 2 and ( p.project_id = pm.project_id or  p.user_id = u.user_id );

1.使用union,一个select用于创建者,另一个用于具有权限用户不需要Distinct,因为union执行distinct

select u.user_name, p.project_name
   from users u
   inner join projects p on p.user_id = u.user_id
   where u.user_id = 2
 union 
   select u.user_name, p.project_name
   from users u
   inner join permissions pm on pm.user_id = u.user_id
   inner join projects p on p.project_id = pm.project_id
   where u.user_id = 2

在线编辑:https://onecompiler.com/mysql/3y64ukxtp

fcy6dtqo

fcy6dtqo2#

查询中的问题是user_id字段应该同时匹配:

  • userspermissions之间,以捕获允许用户处理的项目
  • usersprojects之间,以捕获用户创建的项目

解决这个问题的一个方法是在这两个结果集之间进行UNION操作。为了使连接更有效,最好将过滤操作(查找特定用户)移到连接操作之前,这就是为什么我将其移到子查询中的原因(在公共表表达式cte的形式下)。

WITH user_details AS(
    SELECT user_id, 
           user_name 
    FROM users
    WHERE user_id = 501
)
SELECT user_details.*,
       projects.project_id,
       projects.project_name,
       projects.user_id         AS project_creator
FROM       user_details 
INNER JOIN projects     
        ON user_details.user_id = projects.user_id 

UNION 

SELECT user_details.*,
       projects.project_id,
       projects.project_name,
       projects.user_id         AS project_creator
FROM       user_details 
INNER JOIN permissions 
        ON user_details.user_id = permissions.user_id
INNER JOIN projects
        ON permissions.project_id = projects.project_id

您可以在示例环境here中进行尝试。

omhiaaxx

omhiaaxx3#

使用此查询:

SELECT project_id FROM projects WHERE user_id = :user_id
UNION ALL
SELECT project_id FROM permissions WHERE user_id = :user_id

您将获得:user_id创建或有权访问的所有项目的id。
将其与运算符IN配合使用:

SELECT p.*, u.user_name
FROM projects p INNER JOIN users u
ON u.user_id = p.user_id
WHERE p.project_id IN (
  SELECT project_id FROM projects WHERE user_id = :user_id
  UNION ALL
  SELECT project_id FROM permissions WHERE user_id = :user_id
);

相关问题