在我的数据库中,我有用户,应用程序和发行版。用户可以通过权限表拥有0..n个应用程序,而一个应用程序可以具有0..n个发行版。
我正在尝试获取至少拥有1个应用程序的用户列表,但该用户的应用程序均未发布任何版本。
模式大致
users permissions apps releases
----- ----------- ---- --------
id user_id id id
email app_id app_id
我认为我对此有一些帮助,但对我来说似乎效率很低,因为我两次提到了权限表,并且使用了嵌套的存在子句。有没有更有效的方式编写此查询?
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
)
);
答案 0 :(得分:2)
第一个total = 0
def process_order(x_list):
for x in len(x_list):
print(f"You filled an order for{x[1]} {x[0]} for a total of {x[1]* x[2]}")
x = [("oranges", 4, 3.22),("gummy bears",1,1.99),("sour bites", 3, 2.33), ("antacid", 1, 5.33)]
while(len(x)>0):
process_order(x)
print("Total price: ${:.2f}".format(total))
在Join
和users
表之间似乎是正确的。您只需要检查permissions
表中是否存在来自联接结果集中的app_id。您可以尝试此查询-
releases
答案 1 :(得分:2)
您只需要在发行版上使用LEFT JOIN
,然后查找发行的应用程序数量(r.app_id为非NULL)为0的情况。如果您想要的只是一个用户列表,我认为您根本不需要JOIN
apps
表,因为JOIN
上的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
答案 2 :(得分:1)
我会做这样的事情,希望对您有所帮助:
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
答案 3 :(得分:0)
您可以尝试的另一种方法是将左联接和内部联接结合起来,如下所示:
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”语句比在查询开始时使用“选择不同的”语句更快地获取唯一的集。