【问题标题】:How do I get the MIN value from two columns along with corresponding id?如何从两列中获取 MIN 值以及相应的 id?
【发布时间】:2018-10-01 10:19:11
【问题描述】:

我的查询确实返回了两列(price_base、price_special)中的最低价格,但它没有返回与找到的最低价格对应的正确 store_id。

我的查询:

SELECT grocery_item.id, grocery_item.category,
grocery_category.name AS cat, grocery_item.name AS itemName,
MIN( if( grocery_price.price_special>0,
grocery_price.price_base)) AS price,
grocery_price.store_id,
grocery_store.name AS storeName
FROM grocery_item
LEFT JOIN grocery_category ON
grocery_category.id=grocery_item.category
LEFT JOIN grocery_price
ON grocery_price.item_id = grocery_item.id
LEFT JOIN grocery_store 
ON grocery_store.id=grocery_price.store_id   
WHERE grocery_price.selection='no'
AND buy='yes'
GROUP BY grocery_price.item_id
ORDER BY store_id, grocery_item.category, grocery_item.name

返回这个:

ID  category    cat     itemName       price    store_id    storeName
92  3   Bread/Bakery    Arnold Bread    2.14    1           Food Lion   

但grocery_price 表包含以下信息:

item_id price_base  price_special   store_id
92      4.29        2.14            9
92      3.99        0.00            1

所以我需要返回的 store_id 是 9(返回的 storeName 不会是 Food Lion)

编辑:基于 Uueerdo 的 cmets 的工作查询(谢谢!)

SELECT minP.item_id, gi.category, gc.name AS cat,
gi.name as itemName,  gp.store_id, 
gs.name AS storeName, minP.price
FROM
(SELECT p.item_id, MIN(IF(p.price_special >0,
p.price_special,p.price_base)) AS price
FROM grocery_item AS i
INNER JOIN grocery_price AS p ON (i.id = p.item_id)
WHERE i.buy = 'yes'
GROUP BY p.item_id) AS minP
INNER JOIN grocery_item AS gi ON minP.item_id = gi.id
INNER JOIN grocery_category AS gc on gi.category = gc.id 
LEFT JOIN grocery_price AS gp
ON minP.price = IF(gp.price_special > 0,
gp.price_special,gp.price_base)
AND gp.item_id = gi.id
INNER JOIN grocery_store AS gs ON gp.store_id = gs.id
GROUP BY gi.id
ORDER BY gs.id, gi.category,gi.name

【问题讨论】:

  • 使用 JOIN ... ON 代替 FROM table1,table2,...
  • 使用正确的JOIN 语法!!!它已经存在了 20 多年了!!!
  • 使用正确的GROUP BY。这个查询甚至没有运行。 t1.name,t1.category, grocery_category.name AS cat, t1.name AS itemName, t1.buy,grocery_price.store_id, grocery_store.name AS storeName 列不在 GROUP BY 子句中。

标签: mysql min


【解决方案1】:

为非分组、非聚合字段返回的值是从分组字段值遇到的值中(有效地)随机选择的。大多数 RDBMS 甚至不认为这样的查询是有效的,甚至更新版本的 MySQL 默认不允许这样的查询。

在像您这样的情况下,您需要与聚合结果关联的非分组值(在这种情况下为最小值);聚合查询必须转换为子查询,该子查询可以连接回聚合表以查找与聚合值对应的源行。

编辑:基本上,您需要稍微不同地看待问题。您目前正在查找商品的最低价格以及列出该商品的一家商店;您需要找到一件商品的最低价格,然后用它来找到以该价格出售该商品的商店


这将为您提供标有“购买”的商品的最低价格:

SELECT p.item_id, MIN(IF(p.price_special > 0,p.price_special,p.price_base)) AS price
FROM grocery_item AS i
INNER JOIN grocery_price AS p ON (i.id = p.item_id)
WHERE i.buy = 'yes'
GROUP BY p.item_id

然后你可以用它来获得其余的结果:

SELECT minP.item_id
   , gi.name
   , gi.category, gc.category_name AS cat, gi.Name as itemName, gi.buy
   , gp.store_id, gp.name AS storeName
   , minP.price
FROM ([the query above]) AS minP
INNER JOIN grocery_item AS gi ON minP.item_id = gi.id
INNER JOIN grocery_category AS gc on gi.category = gc.grocery_category_id 
    /* Guessing on this join since grocery_category_id 
       was not qualified with it's table name */
INNER JOIN grocery_price AS gp 
   ON minP.price = IF(gp.price_special > 0,gp.price_special,gp.price_base)
   /* Alternatively: ON minP.price IN (gp.price_special, gp.price_base) 
      ... though this could cause false positives if the minP.price is 0 
          from one store's base price being "free"
   */
INNER JOIN grocery_store AS gs ON gp.store_id = gs.id
;

【讨论】:

  • “你需要找到一件商品的最低价格,并用它来找到以该价格出售该商品的商店”——虽然我一直无法弄清楚,但这是有道理的出来吧。
  • @bp163 添加了最终查询(为了便于理解分两部分);还要注意连接(以及我进行连接的顺序)如何使连接比带有碰巧“连接”它们的条件列表的表列表更清晰。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-21
  • 2014-09-12
  • 2017-06-10
  • 2014-09-06
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
相关资源
最近更新 更多