Mysql SQL查询以查找应用程序未发布的用户

Mysql SQL查询以查找应用程序未发布的用户,mysql,sql,performance,join,exists,Mysql,Sql,Performance,Join,Exists,在我的数据库中,我有用户、应用程序和版本。用户可以通过权限表拥有0..n个应用程序,而应用程序可以拥有0..n个版本 我正在尝试获取至少有1个应用程序的用户列表,但该用户的应用程序都没有发布版本 模式大致相同 users permissions apps releases ----- ----------- ---- -------- id user_id id id email app_id app_id 我想我已经解决了这个问题

在我的数据库中,我有用户、应用程序和版本。用户可以通过权限表拥有0..n个应用程序,而应用程序可以拥有0..n个版本

我正在尝试获取至少有1个应用程序的用户列表,但该用户的应用程序都没有发布版本

模式大致相同

users  permissions  apps  releases
-----  -----------  ----  --------
id     user_id      id    id
email  app_id             app_id
我想我已经解决了这个问题,但它对我来说效率很低,因为我两次提到permissions表,并且使用嵌套的exists子句。有没有更有效的方法来编写此查询

select u.email from users u 
    join permissions p on p.user_id = u.id 
    where not exists (
        select a.id from apps a 
            join permissions p on p.app_id = a.id 
            where p.user_id = u.id and exists (
                select r.id from releases r 
                    where r.app_id = a.id
            )
    ); 

第一个
Join
用户
权限
表之间似乎是正确的。您只需检查加入结果集中的应用程序id是否存在于
releases
表中。您可以尝试此查询-

select u.email from users u 
join permissions p on p.user_id = u.id 
where not exists ( Select 1 from releases r where r.App_id = p.app_id)

您可以尝试的另一种方法是左连接和内连接的组合,如下所示:

Select
    email
From users u
Inner Join (
    Select
        p.user_id
        , p.app_id
     From permissions p
     Left Join releases r
        on p.app_id = r.app_id
     Where r.app_id is null) a
on u.user_id = a.user_id
Group by email
在不知道不同表的大小(以及SQL将尝试连接多少行)的情况下,很难判断此解决方案与之前发布的解决方案之间哪一个更快


有一件事很清楚——如果末尾没有“通过电子邮件分组”这一行,您可能会看到用户的电子邮件在您的列表中重复多次。一般来说,有关SQL的文献指出,在查询结束时使用“group by”语句比在查询开始时使用“select distinct”语句更快地获得不同的集合。

我将这样做,希望这有助于:

SELECT
    u.id, u.email
FROM
    users AS u
INNER JOIN
    permissions AS p ON p.user_id = u.id
LEFT JOIN
    releases AS r ON r.app_id = p.app_id
GROUP BY
    u.id, u.email
HAVING
    SUM(CASE WHEN r.id IS NOT NULL THEN 1 ELSE 0 END) = 0

您只需在发布时使用
左连接
,然后查找已发布应用程序的数量(r.app_id为非空)为0的情况。如果您只需要一个用户列表,我认为您根本不需要
加入
应用程序
表,因为
加入
权限
将确保只包括对一个或多个应用程序具有权限的用户

SELECT u.email
FROM users u
JOIN permissions p ON p.user_id = u.id
LEFT JOIN releases r ON r.app_id = p.app_id
GROUP BY u.email
HAVING COUNT(r.app_id) = 0

看看这些答案中有没有一个解决了你的问题?如果是,请将答案标记为已接受(向上/向下投票箭头下方的绿色箭头)。否则,您可以提供更多信息来帮助解决问题。看,我一开始是这样想的,但是假设用户A拥有APP1和APP2的权限,其中APP1有发布,而APP2没有任何发布。我认为该用户将被选中,但与此相反:但该用户的应用程序都没有发布任何版本。@D.Smania您完全正确。感谢您指出这一点。这将显示一个拥有APP1和APP2权限但只有APP2已发布的用户,该用户不符合问题条件“该用户的应用程序均未发布任何版本”