内部连接3个表用于许可

时间:2012-08-21 20:35:23

标签: mysql sql

嘿所有我试图用表用户中的所有记录填充我的查询,让每个人检查他们的权限来自其他2个表(user_permission& permission)。

我当前的查询是:

SELECT user.id, user.email,  
CONCAT(' ', user.name, user.username) AS theNameUserName,
IF(user.opted_in = 0, 'NO', 'YES') AS optedIn  
FROM user AS user, user_permission AS userPerm
INNER JOIN permission AS Perm ON Perm.id = userPerm.permission_id;

哪个执行没有问题,但一遍又一遍只有相同的数据。它只返回 1000条记录,每次重复3次。我在用户表中有 470个用户,因此我应该返回所有470条记录,并告诉我他们的许可。

我需要对上面的查询做些什么才能做到这一点? User.id 将与 user_permission user_id 匹配。

user_permission表格布局:

  user_id  permission_id
       1        1
       2        3
       3        3
       8        4
       9        4
      10        4
      11        4
      12        4
      13        4
       ....etc etc

权限表:

   id            name
    4      registered users
    3      editor
    2      developer
    1      administrator
    5      registered builders

用户表:

   id      name         email                username           opted_in
   11   David Dxxxx     dxxxxx@exxxx.com    dxxxxxx@exxxxx.com      0
   12   Michael Lxx     sx@sprintmail.com   sxxxxxx@sxxxxx.com      0
   13   Jon Fxxxxxx     jxxxxxxx@xxx.com    jxxxxxx@sxxxxx.com      0
        etc etc .......

1 个答案:

答案 0 :(得分:2)

你有一个不同寻常的隐式(逗号分隔)INNER JOIN和明确的混合,最终你没有条件加入useruser_permission这就是为什么你会得到一个笛卡尔两者的产物。您的JOIN应如下所示:

SELECT
  user.id,
  user.email,  
  CONCAT_WS(' ', user.name, user.username) AS theNameUserName,
  IF(user.opted_in = 0, 'NO', 'YES') AS optedIn  
FROM 
  user
  LEFT JOIN user_permission AS userPerm ON user.id = userPerm.user_id
  INNER JOIN permission AS Perm ON Perm.id = userPerm.permission_id;

我已在LEFT JOINuser之间替换了user_permission,以将没有相关权限的用户列为NULL。如果应从结果中省略它们,请改用INNER JOIN

我还用CONCAT()替换你的CONCAT_WS(),因为你先占用了空间 - 你本来就是在字符串前面贴了一个空格而不是把它们分开(如果这就是你的话)意)。

最后一点:IF()中的SELECT条件适用于MySQL和其他一些RDBMS,但最便携的版本会使用CASE代替:

CASE WHEN user.opted_in = 0 THEN 'NO' ELSE 'YES' END AS theNameUserName

...如果您希望在不同的RDBMS上运行此操作,那么只是一个建议。