简体   繁体   English

当与LEFT JOIN,WHERE和OR结合使用时,MySQL JOIN返回不相关的行

[英]MySQL JOIN returning unrelated rows when combined with LEFT JOIN, WHERE and OR

I have the following table structure. 我有以下表格结构。 The idea is that users have permissions to a forum either by their class or specific user overrides. 想法是,用户可以通过其班级或特定的用户替代权限来访问论坛。 ('action' in both cases is an enum with values 'read' & 'write') (两种情况下的“动作”都是具有值“读”和“写”的枚举)

user (id, class)
forum (id, name)
forum_permissions (forum_id, class_id, action)
forum_user_permissions (forum_id, user_id, action)

With the following query, I'm getting extra results based on rows in forum_permissions that I don't expect. 通过以下查询,我得到了基于我所不期望的forum_permissions中的行的额外结果。 By this I mean that every row on forum_permissions with forum_id = 3 is returned even though the class_id does not match. 我的意思是,即使class_id不匹配,也会返回forum_permissions上forum_id = 3的每一行。

SELECT      forum.id AS forum_id, forum.name
FROM        forum
JOIN        forum_permissions ON forum_permissions.forum_id = forum.id
LEFT JOIN   forum_user_permissions ON ( 
             forum_user_permissions.forum_id = forum.id AND forum_user_permissions.user_id = 3 )
WHERE       (( forum_permissions.class_id = 1 AND forum_permissions.action = 'read' )
              OR
             ( forum_user_permissions.action = 'read' ))

eg I get this: 例如我明白了:

FORUM_ID    NAME
   1        chat
   2        support
   3        secret
   3        secret
   3        secret
   3        secret

but expected this: 但期望这样:

FORUM_ID    NAME
   1        chat
   2        support
   3        secret

I have made an SQL Fiddle with the specific example including data http://sqlfiddle.com/#!2/75c3a/5/0 我使用包含数据http://sqlfiddle.com/#!2/75c3a/5/0的特定示例制作了SQL Fiddle

Your left join is adding those extra lines. 您的左联接正在添加这些额外的行。 mybe if you change the WHERE mybe如果你改变了WHERE

WHERE  forum_user_permissions.user_id is not null and (
  (forum_permissions.class_id = 1 AND forum_permissions.action = 'read')
OR
  (forum_user_permissions.action = 'read')
)

Or 要么

SELECT
 forum.id AS forum_id, forum.name
FROM
 forum
JOIN
 forum_permissions 
  ON
    forum_permissions.forum_id = forum.id
LEFT JOIN
 forum_user_permissions
  ON (
    forum_user_permissions.forum_id = forum.id 
  )
WHERE forum_user_permissions.user_id = 3 and (
 (forum_permissions.class_id = 1 AND forum_permissions.action = 'read')
 OR
 (forum_user_permissions.action = 'read')
 )

But it depends on the results your are trying to get 但这取决于您尝试获得的结果

Okay, I solved it myself by using LEFT JOIN's for both permission tables, rather than put the logic in a WHERE clause. 好的,我自己通过对两个权限表使用LEFT JOIN来解决了问题,而不是将逻辑放在WHERE子句中。 I'm not very sure if this is a better approach than my first attempt and will gladly upvote if someone can explain. 我不太确定这是否比我的第一次尝试更好,如果有人可以解释,我会很乐意支持。

SELECT    forum.id AS forum_id, forum.name
FROM      forum
LEFT JOIN forum_permissions
        ON ( forum_permissions.forum_id = forum.id
        AND forum_permissions.class_id = 1
        AND forum_permissions.action = 'read' )
LEFT JOIN forum_user_permissions
       ON ( forum_user_permissions.forum_id = forum.id 
       AND forum_user_permissions.user_id = 3
       AND forum_user_permissions.action = 'read' )
WHERE forum_permissions.forum_id IS NOT null OR forum_user_permissions.forum_id IS NOT null

The full dataset is included below as I guess the fiddle will expire at some point. 完整的数据集包括在下面,因为我猜小提琴将在某个时候到期。

INSERT INTO user
    (`id`, `class`)
VALUES
    (1, 1), (2, 1), (3, 1), (4, 2);

INSERT INTO forum
    (`id`, `name`)
VALUES
    (1, 'chat'), (2, 'support'), (3, 'secret'); 

INSERT INTO forum_permissions
    (`forum_id`, `class_id`, `action`)
VALUES
    (1, 1, 'read'), (1, 1, 'write'),
    (1, 2, 'read'), (1, 2, 'write'),
    (2, 1, 'read'), (2, 1, 'write'),
    (2, 2, 'read'), (2, 2, 'write'),
    (3, 2, 'read'), (3, 2, 'write'),
    (3, 3, 'read'), (3, 3, 'write');

INSERT INTO forum_user_permissions
    (`forum_id`, `user_id`, `action`)
VALUES
    (3, 3, 'read'), (3, 3, 'write');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM