【问题标题】:Determine which source row is returned for SQL MAX() function确定为 SQL MAX() 函数返回的源行
【发布时间】:2020-05-19 19:59:30
【问题描述】:

假设我有下表:

+---------+-------------------------------------+-------------+---------+--------+--------+------------+----------+---------+------------+
| book_id | book_name                           | isbn_no     | cate_id | aut_id | pub_id | dt_of_pub  | pub_lang | no_page | book_price |
+---------+-------------------------------------+-------------+---------+--------+--------+------------+----------+---------+------------+
| BK001   | Introduction to Electrodynamics     | 0000979001  | CA001   | AUT001 | P003   | 2001-05-08 | English  |     201 |      85.00 |
| BK002   | Understanding of Steel Construction | 0000979002  | CA002   | AUT002 | P001   | 2003-07-15 | English  |     300 |     105.50 |
| BK003   | Guide to Networking                 | 0000979003  | CA003   | AUT003 | P002   | 2002-09-10 | Hindi    |     510 |     200.00 |
| BK004   | Transfer  of Heat and Mass          | 0000979004  | CA002   | AUT004 | P004   | 2004-02-16 | English  |     600 |     250.00 |
| BK005   | Conceptual Physics                  | 0000979005  | CA001   | AUT005 | P006   | 2003-07-16 | NULL     |     345 |     145.00 |
| BK006   | Fundamentals of Heat                | 0000979006  | CA001   | AUT006 | P005   | 2003-08-10 | German   |     247 |     112.00 |
| BK007   | Advanced 3d Graphics                | 0000979007  | CA003   | AUT007 | P002   | 2004-02-16 | Hindi    |     165 |      56.00 |
| BK008   | Human Anatomy                       | 0000979008  | CA005   | AUT008 | P006   | 2001-05-17 | German   |      88 |      50.50 |
| BK009   | Mental Health Nursing               | 0000979009  | CA005   | AUT009 | P007   | 2004-02-10 | English  |     350 |     145.00 |
| BK010   | Fundamentals of Thermodynamics      | 0000979010  | CA002   | AUT010 | P007   | 2002-10-14 | English  |     400 |     225.00 |
| BK011   | The Experimental Analysis of Cat    | 0000979011  | CA004   | AUT011 | P005   | 2007-06-09 | French   |     225 |      95.00 |
| BK012   | The Nature  of World                | 0000979012  | CA004   | AUT005 | P008   | 2005-12-20 | English  |     350 |      88.00 |
| BK013   | Environment a Sustainable Future    | 0000979013  | CA004   | AUT012 | P001   | 2003-10-27 | German   |     165 |     100.00 |
| BK014   | Concepts in Health                  | 0000979014  | CA005   | AUT013 | P004   | 2001-08-25 | NULL     |     320 |     180.00 |
| BK015   | Anatomy & Physiology                | 0000979015  | CA005   | AUT014 | P008   | 2000-10-10 | Hindi    |     225 |     135.00 |
| BK016   | Networks and Telecommunications     | 00009790_16 | CA003   | AUT015 | P003   | 2002-01-01 | French   |      95 |      45.00 |
+---------+-------------------------------------+-------------+---------+--------+--------+------------+----------+---------+------------+

我的查询是:

SELECT cate_id, MAX( book_price)
FROM book_mast
GROUP BY cate_id;

它返回:

+---------+-----------------+
| cate_id | MAX(book_price) |
+---------+-----------------+
| CA001   |          145.00 | 
| CA002   |          250.00 | 
| CA003   |          200.00 | 
| CA004   |          100.00 | 
| CA005   |          180.00 | 
+---------+-----------------+

现在说第一条记录 - CA001,最高图书价格为 145。

  1. 如何确定它是 book_id=BK005 的概念物理学?

  2. 如果有两条记录匹配相同的最大值会怎样?

(这个问题是我试图解决的一个大视图的一部分,很抱歉无耻地复制https://www.w3resource.com/mysql/aggregate-functions-and-grouping/aggregate-functions-and-grouping-max-with-group-by.php的例子。这只是为了解释问题)

【问题讨论】:

  • 搜索“mysql best-n-per-group”可能会产生一些不错的阅读效果。这是 n=1 的一种特殊情况,可以用 MAX 来解决。还有其他选择。
  • 指定 MySQL 版本。
  • 如果有两条记录匹配相同的最大值会发生什么?只有你可以说在这种情况下必须发生什么 - 要么全部要么选择其中一个必须返回一些附加条件(例如,前者按字母顺序)。

标签: mysql sql max


【解决方案1】:

您可以使用 group by 获取每个 cate_id 的最高价格,然后与原始表进行内连接以获取 book_id

SELECT a.cate_id, a.book_price as 'MAX(book_price)', a.book_id
FROM book_mast a
inner join 
(
    SELECT x.cate_id, MAX(x.book_price) AS max_price
    FROM book_mast x
    GROUP BY x.cate_id;
) b
on a.cate_id = b.cate_id AND a.book_price = b.max_price

【讨论】:

  • 与其他答案一样,这可以以相同的最高图书价格返回多个 cate_id 副本。 OP 询问这种情况(尽管没有指定适当的结果)。其他答案上的类似 cmets。
  • 我不明白为什么这个答案与来自@scaisEdge 的答案相同?
【解决方案2】:

您需要在聚合结果和基于聚合结果的原始值之间进行连接

select m.* from book_mast m
inner join  (
    SELECT cate_id, MAX( book_price) max_price
    FROM book_mast
    GROUP BY cate_id

    ) t on t.cate_id = m.cate_id and t.max_price = m.book_price

【讨论】:

  • 注意:如果多行相同的 cate_id 具有相同的 book_price,这可以为每个 cate_id 返回多行。这种情况下的预期行为尚未定义。
  • @Strawberry 。正确..添加了表格参考..谢谢
  • @Strawberry 我猜你有自己的方式来处理 cmets,但尽管已经处理了很长时间,但我还是不明白......无论如何......谢谢
  • OK - VBoka 在一小时前修复了错误;在我评论之后。
【解决方案3】:
SELECT bm1.book_id
       , bm1.book_name
       , bm1.cate_id
       , bm1.book_price
FROM book_mast bm1
where bm1.book_price = (SELECT MAX( bm2.book_price )
                        FROM book_mast bm2
                        where bm2.cate_id = bm1.cate_id);

这是他的示例的一个小演示:DEMO

【讨论】:

  • 如果两本书的价格相同,每个 cate_id 也可能产生多个结果
  • 许多 SQL 查询规划器将(谢天谢地)将其转换为连接,而不是将其视为依赖子查询。我建议一般使用显式连接,而不必依赖此类实现细节。例如,我在 SQL Server 中工作,不知道 MySQL 将如何处理它:)
  • 子查询中的GROUP BY 是不必要的。
猜你喜欢
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多