【问题标题】:DISTINCT or GROUP BY used with NOT IN returns wrong results与 NOT IN 一起使用的 DISTINCT 或 GROUP BY 返回错误的结果
【发布时间】:2012-07-16 05:18:57
【问题描述】:

我有两张桌子
具有列的用户: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 模块 Views(由于 Views 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 中做到这一点?

【问题讨论】:

    标签: sql drupal drupal-7


    【解决方案1】:

    我需要返回所有没有角色 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
            )
    

    【讨论】:

    • 谢谢!这就像一个魅力!当我说 4 和 5 时,我并不完全清楚,我的意思是或,这很好用!
    【解决方案2】:

    如果您想检查 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
            ) 
    

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

    【讨论】:

    • 我的问题不够清楚。我的意思是说 4 或 5 但这确实像宣传的那样有效!事实上,我玩得越多,我就越意识到你可以通过它获得多少细粒度的控制。谢谢!
    【解决方案3】:

    我想要那个:

    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
    

    【讨论】:

    • 快速测试表明这似乎有效。明天晚些时候我真的必须深入挖掘,以确定它是否返回与第一个答案不同的结果。这是 NOT EXISTS 的简写吗?
    • 这不是 NOT EXISTS 的简写。此解决方案避免了通过子查询。您可以测试两种解决方案之间的速度吗?我认为我的解决方案更快。
    • 现在,我有一个很小的数据集(约 50 条记录),每次我运行查询时,这两种解决方案都并驾齐驱。当我有更大的数据集(或创建假数据集的时间)时,我会尽快回复您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多