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
将在我所处的位置赢得这场竞争——它可以更快,但决不会更慢。)