SQL 查询以查找使用没有版本的应用的用户

SQL query to find users with apps with no releases

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

我正在尝试获取至少拥有 1 个应用的用户列表,但该用户的 none 个应用有任何版本。

架构大致是

users  permissions  apps  releases
-----  -----------  ----  --------
id     user_id      id    id
email  app_id             app_id

认为 我有一些方法可以解决这个问题,但它对我来说似乎效率低下,因为我提到了权限 table 两次并且我使用的是嵌套存在条款。有没有更有效的方法来编写此查询?

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 似乎在 userspermissions table 之间是正确的。您只需要检查连接结果集中的 app_id 是否存在于 releases table 中。您可以试试这个查询 -

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 将尝试加入)的情况下,很难说出这个解决方案和之前发布的解决方案之间哪个更快。

有一点很清楚 - 如果末尾没有 'Group by email' 行,您可能会看到用户的电子邮件在您的列表中重复出现多次。通常,关于 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

你只需要在发布上使用一个LEFT JOIN,然后寻找发布的应用数量(r.app_id为非NULL)为0的情况。如果你想要的是用户列表,我认为您根本不需要 JOIN apps table,因为 JOINing on permissions 将确保只有用户包含 1 个或多个应用程序的权限。

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