【问题标题】:MySQL join table return only one matchMySQL 连接表只返回一个匹配项
【发布时间】:2013-10-04 10:27:23
【问题描述】:

我在 MySQL 查询中遇到 JOIN 问题。不知何故,我无法找出为什么我的结果不是我想要的。

我有两张桌子,一张桌子订单和一张桌子产品。表产品包含订单的 order.id。所以一个订单可以有多个产品,例如表 products 包含两个订单记录。

我需要的结果是产品的增值税为 21 的所有订单。

表格示例。

orders
id | customer
---------------
1  | John Doe
2  | Hello World

order_products
id | order_id | product          | vat
1  | 1        | Porsche 911 GT4  | 21
2  | 1        | Audi R8 LMS      | 21
3  | 1        | Ferrari Enzo     | 19
3  | 2        | Bugatti Veyron   | 19

不,我想要所有产品增值税为 21 的订单。所以我将在 order_products 表上执行 LEFT JOIN:

SELECT orders.id, orders.customer, order_products.product FROM orders LEFT JOIN order_products ON orders.id = order_products.order_id WHERE order_products.vat = '21'

这将返回以下内容:

1 John Doe Porsche
1 John Doe Audi R8 LMS

但我只需要一个结果,因为 orders.id 对我很重要,而不是订单中的所有产品。我只加入 order_products 以获得仅含增值税 21 的订单。目前我没有解决此问题的选项。即使在阅读了有关此站点和其他站点上的加入的几个主题之后。

【问题讨论】:

  • 使用左连接的内连接意图
  • 我做了,返回相同。我真正的查询是在另一个表上,这些表只是虚构的,但结构是一样的
  • 如果你有 2 个不同的 order_ids 怎么办?
  • @DanFromGermany,没关系,所有包含增值税为 21 的产品的订单。
  • 通常,不关心返回的结果表明设计不佳。

标签: mysql join left-join


【解决方案1】:

首先,您不会退回任何没有产品的订单,因此不需要左连接...内连接就可以了。

如果orders_product 对您不重要,您可以使用子查询而不从orders_product 中选择任何列。不过,对于您当前的查询,您正在选择一列。

类似...

SELECT id, customer 
FROM orders 
WHERE order_id IN (SELECT order_id FROM order_products
                   WHERE order_products.vat = '21');

如果您不想使用相关子查询,可以使用 group by 或 distinct

SELECT orders.id, orders.customer 
FROM orders 
INNER JOIN order_products ON orders.id = order_products.order_id 
WHERE order_products.vat = '21'
GROUP BY orders.id, orders.customer;

或者...

SELECT DISTINCT orders.id, orders.customer 
FROM orders 
INNER JOIN order_products ON orders.id = order_products.order_id 
WHERE order_products.vat = '21';

【讨论】:

  • 这也返回了正确的订单,orders_products 确实不重要,只有orders.idorders.customer。 @Jim 的回答也是正确的,但是不知道哪个更快,额外的 select 还是 group by!
  • 哪个更快取决于表格的基数,甚至可能随着时间而改变。如果性能确实很重要(过早的优化是万恶之源,对吧?)m 你应该测试它们。但是,您可能最好选择您认为更清楚的那个。
  • 在我的数据库中,大约 120k 个订单和 150k 个产品的性能似乎是相同的。所以我会选择GROUP BY,因为它对我来说似乎更清楚。
【解决方案2】:

如果您只关心订单,则可以按订单 ID 分组:

SELECT orders.id, orders.customer, order_products.product 
FROM orders 
LEFT JOIN order_products ON orders.id = order_products.order_id 
WHERE order_products.vat = '21'
GROUP BY orders.id;

但请注意,order_products.product 只是其中一种产品。如果您希望显示所有产品但在一列中,您可以使用GROUP_CONCAT

SELECT orders.id, orders.customer, GROUP_CONCAT(order_products.product) 
FROM orders 
LEFT JOIN order_products ON orders.id = order_products.order_id 
WHERE order_products.vat = '21'
GROUP BY orders.id;

这将返回:

1 John Doe Porsche, Audi R8 LMS

【讨论】:

  • 其实我不需要order_products.product,只要orders.id就够了。所以GROUP BY 是我想我需要的!
  • 我将 Steve Clanton 的答案标记为“答案”,因为它包含两种方法,包括您的方法!感谢您的回答!
  • @Timo002 没问题 :)
【解决方案3】:
SELECT DISTINCT o.id
              , o.customer
           FROM orders o
           JOIN order_products op
             ON op.order_id = o.id 
          WHERE op.vat = 21;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2011-09-30
    相关资源
    最近更新 更多