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

时间:2014-06-08 21:46:59

标签: mysql join

我有以下表格结构。这个想法是用户通过他们的类或特定用户覆盖对论坛拥有权限。 ('行动'在这两种情况下都是带有价值观的枚举'阅读''写')

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

通过以下查询,我可以根据forum_permissions中我不希望的行获得额外的结果。我的意思是,即使class_id不匹配,forum_id = 3的forum_permissions上的每一行都会被返回。

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' ))

e.g。我明白了:

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

但期望这样:

FORUM_ID    NAME
   1        chat
   2        support
   3        secret

我使用包含数据http://sqlfiddle.com/#!2/75c3a/5/0

的具体示例制作了一个SQL小提琴

2 个答案:

答案 0 :(得分:0)

您的左连接正在添加这些额外的行。 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')
)

或者

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')
 )

但这取决于你想要获得的结果

答案 1 :(得分:0)

好吧,我自己通过对两个权限表使用LEFT JOIN来解决它,而不是将逻辑放在WHERE子句中。我不太确定这是否比我的第一次尝试更好,如果有人可以解释的话,我很乐意投票。

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

完整的数据集包含在下面,因为我猜小提琴将在某个时候到期。

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');