如何正确查询数据库中最高价、最低价商品及其商品编号?
问题原因与解决方案
你遇到的问题核心是聚合函数(MAX/MIN)和非聚合列(ArtNr)混用但未合理分组导致的。在很多数据库(比如MySQL关闭ONLY_FULL_GROUP_BY模式时),这种写法不会报错,但会随机返回一个非聚合列的值——你这里刚好拿到了最低价对应的ArtNr,完全是巧合,逻辑上根本无法保证ArtNr和MAX(Price)/MIN(Price)是对应的。
下面给你几种靠谱的修正方案,按需选择即可:
方案1:用UNION ALL列出所有最高/最低价商品(推荐,支持多同价商品)
如果存在多个商品共享最高价或最低价,这个方案会把它们全部列出来,结果更准确:
-- 先查询所有最高价商品,再查询所有最低价商品,合并结果 SELECT ArtNr, Price AS Item_Price, 'Most expensive' AS Price_Category FROM article WHERE Price = (SELECT MAX(Price) FROM article) UNION ALL SELECT ArtNr, Price AS Item_Price, 'Cheapest' AS Price_Category FROM article WHERE Price = (SELECT MIN(Price) FROM article);
方案2:用窗口函数(适合MySQL 8+/PostgreSQL/SQL Server等现代数据库)
窗口函数能更灵活处理这类关联聚合场景,比如你想把最高/最低价的信息放在同一行显示:
SELECT DISTINCT -- 获取价格最高的第一个商品编号和价格 FIRST_VALUE(ArtNr) OVER (ORDER BY Price DESC) AS Top_Price_ArtNr, FIRST_VALUE(Price) OVER (ORDER BY Price DESC) AS Top_Price, -- 获取价格最低的第一个商品编号和价格 FIRST_VALUE(ArtNr) OVER (ORDER BY Price ASC) AS Lowest_Price_ArtNr, FIRST_VALUE(Price) OVER (ORDER BY Price ASC) AS Lowest_Price FROM article;
如果需要列出所有同价商品,可把FIRST_VALUE换成GROUP_CONCAT(ArtNr)(MySQL)或ARRAY_AGG(ArtNr)(PostgreSQL)。
方案3:子查询作为列(适合只需要一行结果的场景)
如果只需要一行展示最高/最低价对应的编号和价格,可用子查询直接作为字段:
SELECT -- 取最高价对应的一个商品编号(加LIMIT 1避免多同价时返回多行报错) (SELECT ArtNr FROM article WHERE Price = (SELECT MAX(Price) FROM article) LIMIT 1) AS Most_expensive_ArtNr, (SELECT MAX(Price) FROM article) AS Most_expensive_Price, -- 取最低价对应的一个商品编号 (SELECT ArtNr FROM article WHERE Price = (SELECT MIN(Price) FROM article) LIMIT 1) AS Cheapest_ArtNr, (SELECT MIN(Price) FROM article) AS Cheapest_Price;
注意:如果有多个同价商品,这个方案只会返回其中一个,若需要全部显示,优先选方案1。
内容的提问来源于stack exchange,提问作者Henri__99
相关产品推荐
相关产品推荐

