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
似乎在 users
和 permissions
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,因为 JOIN
ing 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
在我的数据库中,我有用户、应用程序和版本。一个用户可以通过权限拥有 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
似乎在 users
和 permissions
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,因为 JOIN
ing 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