Sql 内连接中的多个条件
我有两个表Sql 内连接中的多个条件,sql,postgresql,relational-division,Sql,Postgresql,Relational Division,我有两个表user和product,它们有一对多的关系(一个user可能有多个products) 我想创建一个查询来获取所有同时有一个橘子和一个香蕉的用户。在我下面的例子中,这将是john和leeroy 如何制定查询以实现此目的? 只有一个条件,我想: SELECT * FROM "user" INNER JOIN "product" ON "product"."fk_user" = "user"."id" WHERE "product"."product" = 'banana'; 用户表
user
和product
,它们有一对多的关系(一个user
可能有多个product
s)
我想创建一个查询来获取所有同时有一个橘子和一个香蕉的用户。在我下面的例子中,这将是john
和leeroy
如何制定查询以实现此目的?
只有一个条件,我想:
SELECT * FROM "user"
INNER JOIN "product" ON "product"."fk_user" = "user"."id"
WHERE "product"."product" = 'banana';
用户
表
╔════╦═════════╗
║ id ║ name ║
╠════╬═════════╣
║ 1 ║ michael ║
╠════╬═════════╣
║ 2 ║ john ║
╠════╬═════════╣
║ 3 ║ leeroy ║
╠════╬═════════╣
║ 4 ║ tony ║
╚════╩═════════╝
╔═════════╦═════════╗
║ product ║ fk_user ║
╠═════════╬═════════╣
║ orange ║ 1 ║
╠═════════╬═════════╣
║ orange ║ 2 ║
╠═════════╬═════════╣
║ banana ║ 2 ║
╠═════════╬═════════╣
║ banana ║ 3 ║
╠═════════╬═════════╣
║ orange ║ 3 ║
╠═════════╬═════════╣
║ banana ║ 4 ║
╚═════════╩═════════╝
产品
表
╔════╦═════════╗
║ id ║ name ║
╠════╬═════════╣
║ 1 ║ michael ║
╠════╬═════════╣
║ 2 ║ john ║
╠════╬═════════╣
║ 3 ║ leeroy ║
╠════╬═════════╣
║ 4 ║ tony ║
╚════╩═════════╝
╔═════════╦═════════╗
║ product ║ fk_user ║
╠═════════╬═════════╣
║ orange ║ 1 ║
╠═════════╬═════════╣
║ orange ║ 2 ║
╠═════════╬═════════╣
║ banana ║ 2 ║
╠═════════╬═════════╣
║ banana ║ 3 ║
╠═════════╬═════════╣
║ orange ║ 3 ║
╠═════════╬═════════╣
║ banana ║ 4 ║
╚═════════╩═════════╝
可以使用两个联接:
SELECT u.*
FROM user u
INNER JOIN product p1
ON p1.fk_user=u.id
AND p1.product='banana'
INNER JOIN product p2
ON p2.fk_user=u.id
AND p2.product='orange'
可以使用两个联接:
SELECT u.*
FROM user u
INNER JOIN product p1
ON p1.fk_user=u.id
AND p1.product='banana'
INNER JOIN product p2
ON p2.fk_user=u.id
AND p2.product='orange'
按用户分组并使用查看用户的产品
select *
from user
where id in
(
select fk_user
from product
group by fk_user
having count(case when product = 'orange' then 1 end) > 0
and count(case when product = 'banana' then 1 end) > 0
);
编辑:我应该补充一点,有几种方法可以编写这样的子查询。WHERE
子句可以加快速度,使用该子句,您可以计算找到的不同产品:
select *
from user
where id in
(
select fk_user
from product
where product in ('orange', 'banana')
group by fk_user
having count(distinct product) = 2 -- two different products: orange and banana
);
按用户分组并使用查看用户的产品
select *
from user
where id in
(
select fk_user
from product
group by fk_user
having count(case when product = 'orange' then 1 end) > 0
and count(case when product = 'banana' then 1 end) > 0
);
编辑:我应该补充一点,有几种方法可以编写这样的子查询。WHERE
子句可以加快速度,使用该子句,您可以计算找到的不同产品:
select *
from user
where id in
(
select fk_user
from product
where product in ('orange', 'banana')
group by fk_user
having count(distinct product) = 2 -- two different products: orange and banana
);
最直接的声明(IMHO)是在
子句中使用两个:
select *
from user
where id in
(
select fk_user
from product
WHERE product = 'orange')
and id in
(
select fk_user
from product
WHERE product = 'banana')
最直接的声明(IMHO)是在
子句中使用两个:
select *
from user
where id in
(
select fk_user
from product
WHERE product = 'orange')
and id in
(
select fk_user
from product
WHERE product = 'banana')
如果只需要用户id而不需要名称,可以使用聚合:
SELECT p.fk_user
FROM product p
WHERE p.product in ('banana', 'orange')
GROUP BY p.fk_user
HAVING COUNT(*) FILTER (WHERE p.product = 'banana') > 0 AND
COUNT(*) FILTER (WHERE p.product = 'orange') > 0;
如果您还需要user
中的其他列,我会使用DStanley建议的版本中的,尽管我会使用EXISTS
而不是中的如果您只需要用户id而不是名称,可以使用聚合:
SELECT p.fk_user
FROM product p
WHERE p.product in ('banana', 'orange')
GROUP BY p.fk_user
HAVING COUNT(*) FILTER (WHERE p.product = 'banana') > 0 AND
COUNT(*) FILTER (WHERE p.product = 'orange') > 0;
如果您还需要user
中的其他列,我会选择DStanley建议的版本中的,尽管我会使用EXISTS
而不是中的,这是一种情况。
如果(like是典型的情况,您的样本数据似乎支持它)
- 您所需要的只是用户ID
- 存在强制引用完整性的
外键
约束
- 以及对
产品(产品,fk\U用户)
-(隐式用于我的查询)的唯一约束
。。那么这是最快的速度:
SELECT fk_user
FROM product b
JOIN product o USING (fk_user)
WHERE b.product = 'banana'
AND o.product = 'orange';
我们在这里收集了大量基本技术:
最佳选择取决于缺少的规格,以及个人喜好
旁白:是保留的单词,不要将其用作表名。这是的一个例子。
如果(like是典型的情况,您的样本数据似乎支持它)
- 您所需要的只是用户ID
- 存在强制引用完整性的
外键
约束
- 以及对
产品(产品,fk\U用户)
-(隐式用于我的查询)的唯一约束
。。那么这是最快的速度:
SELECT fk_user
FROM product b
JOIN product o USING (fk_user)
WHERE b.product = 'banana'
AND o.product = 'orange';
我们在这里收集了大量基本技术:
最佳选择取决于缺少的规格,以及个人喜好
旁白:是保留的单词,不要将其用作表名。一个联接可能不够。您不需要联接。看看我的答案。顺便说一下,这不是产品表;因为表中的记录不是唯一表示产品的。理想情况下,您应该有一个每个产品一行的产品表和一个链接产品和用户的用户产品表。您是否只需要user\u id
或user
表中的更多列?是否存在强制引用完整性的外键
约束?禁止在产品(产品,fk_用户)
上复制的唯一
约束?你的Postgres版本?一次加入可能不够。你不需要加入。看看我的答案。顺便说一下,这不是产品表;因为表中的记录不是唯一表示产品的。理想情况下,您应该有一个每个产品一行的产品表和一个链接产品和用户的用户产品表。您是否只需要user\u id
或user
表中的更多列?是否存在强制引用完整性的外键
约束?禁止在产品(产品,fk_用户)
上复制的唯一
约束?你对博士后的看法?我想一根香蕉应该是桔子@粘滞的,粘滞的。谢谢我想香蕉应该是橘子的@粘滞的,粘滞的。ThanksCanonical可能不是一个正确的词——我的意图是用“最直接的声明性”的方式来表达。它是表示查询意图的最接近的SQL(EXISTS
是第二个IMHO)足够公平。(EXISTS
将从我的立场赢得这场竞争——它可以更快,但永远不会慢。)Canonical可能不是正确的词——我的意图是说“最直接的声明性”方式。它是表示查询意图的最接近的SQL(EXISTS
是第二个IMHO)足够公平。(EXISTS
将在我所处的位置赢得这场竞争——它可以更快,但决不会更慢。)