MySQL连接表行基于最低单元格值

Posted

技术标签:

【中文标题】MySQL连接表行基于最低单元格值【英文标题】:MySQL Join table row based on lowest cell value 【发布时间】:2014-11-15 06:18:57 【问题描述】:

我在 mysql 数据库中有两个表,如下所示:

产品:

product_id | product_name
-----------+-------------
1          |  shirt
2          |  pants
3          |  socks

PRODUCT_SUPPLIER:(id 为主键)

id  |  supplier_id  |  product_id  |  part_no  |  cost
----+---------------+--------------+-----------+--------
1   |  1            |  1           | s1p1      | 5.00
2   |  1            |  2           | s1p2      | 15.00
3   |  1            |  3           | s1p3      | 25.00
4   |  2            |  1           | s2p1      | 50.00
5   |  2            |  2           | s2p2      | 10.00
6   |  2            |  3           | s2p3      | 5.00

我的目标是一个查询,它连接表并为每个产品输出一行,并以最低成本连接来自相应供应商行的所有字段,如下所示:

product_id | product_name  | supplier_id   |  part_no   | cost
-----------+---------------+---------------+------------+---------
1          | shirt         | 1             |  s1p1      | 5.00
2          | pants         | 2             |  s2p2      | 10.00
3          | socks         | 2             |  s3p3      | 5.00

目前我确实编写了以下查询,它似乎有效,但我想从任何更有经验的 SQL 用户那里知道是否有更清洁、更高效或更好的解决方案?或者如果我的代码有什么本质上的错误?

SELECT p.product_id, p.product_name, s. supplier_id, s.part_no, s.cost
FROM product p
LEFT JOIN product_supplier s ON
   (s.id = (SELECT s2.id 
            FROM product_supplier s2
            WHERE s2.product_id = p.product_id
            ORDER BY s2.cost LIMIT 1));

【问题讨论】:

【参考方案1】:

我会跑:

select p.product_id, p.product_name, s.supplier_id, s.part_no, s.cost
  from product p
  join product_supplier s
    on p.product_id = s.product_id
  join (select product_id, min(cost) as min_cost
          from product_supplier
         group by product_id) v
    on s.product_id = v.product_id
   and s.cost = v.min_cost

我没有看到外连接的意义。每个产品都在 product_supplier 表上吗?如果不是,那么外连接是有意义的(如果是这种情况,将连接更改为内联视图,上面别名为 v 为左连接)。

上述内容可能比您的查询运行得快一点,因为子查询并未针对每一行运行。您当前的子查询依赖于并且相对于产品的每一行。

如果您想消除平局并且不关心随意这样做,您可以在结果末尾添加一个随机数,将查询放入内联视图,然后选择最低/最高/等。每组随机数。这是一个例子:

select product_id, product_name, supplier_id, part_no, cost, min(rnd)
  from (select p.product_id,
               p.product_name,
               s.supplier_id,
               s.part_no,
               s.cost,
               rand() as rnd
          from product p
          join product_supplier s
            on p.product_id = s.product_id
          join (select product_id, min(cost) as min_cost
                 from product_supplier
                group by product_id) v
            on s.product_id = v.product_id
           and s.cost = v.min_cost) x
 group by product_id, product_name, supplier_id, part_no, cost

如果由于某种原因您不希望随机 # 在输出中返回,则可以将上面的整个查询放入内联视图中,然后从中选择除随机 # 之外的所有列。

【讨论】:

谢谢.. 这正是我所希望的那种输入。我还在学习 sql,第二个连接的语法(内联视图?)对我来说是全新的。我很感激你的推动。 是的,理论上,每个产品都应该有至少一个对应的供应商行——尽管实际上很难说是否会一直如此 from 子句中的子查询被称为一些东西,“内联视图”是使用 oracle 的人通常使用的术语,有些人也将其称为“子选择”或“派生表”或仅作为子查询。基本上,如果您要自己运行该查询(我将其别名为 v),您将获得每种产品的最低成本,将该查询作为更大查询的一部分放入内联视图中,您可以加入它, IE。将行限制为成本等于给定项目的最低成本的行。 使用“join”将导致任何没有供应商的产品被淘汰。如果您使用“左连接”(从产品到 product_supplier 的方向),它们不会被淘汰。 我发现这个查询的问题是,如果两个供应商的成本相同,它可以返回多行 - 而我的总是只返回一行。在成本相同的情况下,我不介意选择是任意的 - 但重要的是结果部分与供应商 ID 不匹配。

以上是关于MySQL连接表行基于最低单元格值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery 遍历表行并获取单元格值

忽略其中包含公式的空单元格值

需要一个用户定义的函数来连接excel中的单元格值

如何在 MS Excel 中将单元格值与新行连接起来?

MySQL的连接查询

MySQL的连接查询