2

嘿,我正在尝试使用表用户中的所有记录填充我的查询,并让每个人检查他们从其他 2 个表(user_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 .......
4

1 回答 1

2

你有一个不寻常的隐式(逗号分隔)INNER JOIN和显式混合,最终你没有条件加入useruser_permission这就是你得到两者的笛卡尔积的原因。你JOIN的 s 应该看起来像:

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 JOINbetweenuser和替换了user_permission没有相关权限的用户作为NULL. 如果应该从结果中省略它们,请改用 an INNER JOIN

我也替换了你的CONCAT()CONCAT_WS()因为你首先有空间——你只是在字符串的前面加上一个空格,而不是把两者分开(如果这是你想要的)。

最后一点:您的IF()条件SELECT对 MySQL 和其他一些 RDBMS 非常有效,但最便携的版本将使用 aCASE代替:

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

...如果您希望需要在不同的 RDBMS 上运行它,这只是一个建议。

于 2012-08-21T20:39:12.137 回答