与NOT IN一起使用的DISTINCT或GROUP BY返回错误的结果

时间:2012-07-16 05:18:58

标签: sql drupal drupal-7

我有两张桌子 具有列的用户:uid,名称,邮件等 带有列的users_roles:uid,rid

在users_roles中,每次将角色添加到用户时,都会在users_roles表中列出。所以,假设用户1有角色1和4.在表格中:

users_roles:  
uid | rid  
 1  |  1  
 1  |  4  

我需要返回所有没有角色4或5的用户。我尝试使用Group By和Distinct以及NOT IN。我一直遇到的问题是如果用户同时拥有角色1和4,它们将在结果中返回。以下是我的Group By查询的示例:

SELECT *
FROM users AS u
LEFT JOIN users_roles AS ur ON u.uid = ur.uid
WHERE ur.rid NOT
IN ( 4, 5 )
GROUP BY ur.uid

我尝试过子查询也无济于事,因为问题似乎是Group By在完成查询后合并了行。因此,它只是找到包含uid 1 rid 4的记录并在结果中返回它。

Drupal模块我无法使用的视图(由于View Bulk Operations的安全性问题)通过执行以下操作来完成所需的结果:

LEFT JOIN users_roles ON users.uid = users_roles.uid 
AND (users_roles.rid = '4' OR users_roles.rid = '5')

对于长期维护,我不希望每次添加角色时都必须更新代码,这样就可以进行一次长查询。

我看了下面的内容:
Aggregating Rows
Filtering distinct rows in SQL

虽然有Drupal函数可以让我获取角色ID列表,我可以在其中取消设置我不希望在结果数组中显示的角色,但我觉得我缺少对SQL的基本理解。有没有更好的方法在SQL中执行此操作?

3 个答案:

答案 0 :(得分:0)

  

我需要退回所有没有角色的用户4& 5

select  *
from    users u
where   not exists
        (
        select  *
        from    users_roles ur
        where   ur.rid in (4,5)
                and ur.uid = u.uid
        )

答案 1 :(得分:0)

如果你想检查4和5之间是否存在(而不是其中之一),你可以使用

select  * 
from    users u 
where   not exists 
        ( 
        select  uid
        from    users_roles ur 
        where   ur.rid in (4,5)     
                and ur.uid = u.uid 
    group by uid having count(distinct rid)=2
        ) 

如果列表很长,您可以使用包含所有可能值的映射表,并在上面的查询

中使用它

答案 2 :(得分:0)

我希望如此:

SELECT *
FROM users AS u
LEFT JOIN users_roles AS ur ON (u.uid = ur.uid AND ur.rid IN ( 4, 5 ) )
WHERE ur.rid IS NULL
GROUP BY u.uid