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

时间:2014-09-21 00:10:26

标签: mysql sql left-join greatest-n-per-group

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

PRODUCT:

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 个答案:

答案 0 :(得分: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表上吗?如果没有那么外连接是有意义的(如果是这种情况,则将连接更改为内部视图别名为左上连接)。

上面的查询可能比查询运行得快一些,因为每个行都没有运行子查询。您当前的子查询依赖于每行产品。

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

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

如果由于某种原因你不希望随机#回到输出中,你可以将上面的整个查询放到内联视图中,然后选择所有列,但是从中随机#。