INNER JOIN 中的多个条件

Multiple conditions in INNER JOIN

我有两个 tables userproduct 它们有一对多的关系(一个 user 可能有多个 products ).

我想创建一个查询来获取所有 user 中既有橙子又有香蕉的。在我下面的示例中,这将是 johnleeroy.

如何制定我的查询来做到这一点?

只有一个条件我会喜欢:

SELECT * FROM "user" 
INNER JOIN "product" ON "product"."fk_user" = "user"."id"
WHERE "product"."product" = 'banana';

user table

╔════╦═════════╗
║ id ║ name    ║
╠════╬═════════╣
║ 1  ║ michael ║
╠════╬═════════╣
║ 2  ║ john    ║
╠════╬═════════╣
║ 3  ║ leeroy  ║
╠════╬═════════╣
║ 4  ║ tony    ║
╚════╩═════════╝

product table

╔═════════╦═════════╗
║ 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'

按用户分组并使用HAVING检查用户的产品。

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
);

最直接的声明(恕我直言)是使用两个 IN 子句:

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 建议的 IN 版本,尽管我会使用 EXISTS 而不是 IN .

这是 的情况。
If(like是典型案例,你的示例数据似乎也支持)...

  • 您只需要用户 ID
  • 有一个 FOREIGN KEY 强制参照完整性的约束
  • 和对 product(product, fk_user)UNIQUE 约束 - (对于我的查询隐式

..那么这就是它得到的速度:

SELECT fk_user
FROM   product b
JOIN   product o USING (fk_user)
WHERE  b.product = 'banana'
AND    o.product = 'orange';

我们在这里收集了一系列基本技术:

  • How to filter SQL results in a has-many-through relation

最佳选择取决于缺少的规格 - 以及一定程度上的个人喜好。

旁白:user为保留词,请勿用作table名称。