Bug #18739 | select having field=max(field) causes problems | ||
---|---|---|---|
Submitted: | 3 Apr 2006 14:32 | Modified: | 10 May 2006 18:51 |
Reporter: | Steve Rogers | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
Version: | 5.0.21-BK, 5.0.19 | OS: | Linux (Linux, OS X) |
Assigned to: | Evgeny Potemkin | CPU Architecture: | Any |
[3 Apr 2006 14:32]
Steve Rogers
[3 Apr 2006 16:00]
Valeriy Kravchuk
Thank you for a problem report. Please, specify, what result you expected, and why. I've got the following in mysql client: mysql> select id from maxthings having id = max(id); Empty set (0.01 sec) No crash. (Any crashed of Quuery Browser is a separate problem. Open another bug report about it, if it is repeatable.) If you wanted to get a row with maximal id, it is done in another way (http://dev.mysql.com/doc/refman/5.0/en/example-maximum-row.html): mysql> select id from maxthings where id = (select max(id) from maxthings); +------+ | id | +------+ | 4 | +------+ 1 row in set (0.02 sec)
[3 Apr 2006 16:07]
Valeriy Kravchuk
Yes, if all rows have the same id values, your query "works": mysql> select id from maxthings having id = max(id); +------+ | id | +------+ | 4 | +------+ 1 row in set (0.00 sec) mysql> select id from maxthings; +------+ | id | +------+ | 4 | | 4 | +------+ 2 rows in set (0.00 sec) mysql> insert into maxthings(id) values(2); Query OK, 1 row affected (0.00 sec) mysql> select id from maxthings having id = max(id); Empty set (0.00 sec) And if there are 2 or more values, it does not work. So, it is either a bug or (if it was intended, for a reason unknown to me) a request for proper documentation. This is out of SQL Standard, IMHO, and thus should be explicitely documented in the manual. Verified just as described with 5.0.21-BK on Linux.
[3 Apr 2006 18:10]
Steve Rogers
It is valid SQL, though in practice you would not use this form just to get the max across the whole table - however, that isn't the point. The query should either return the right answer or get kicked back as a syntax error. But it is valid SQL, and the problem is still there if you use a more complex and "realistic" example, like: create table maxthings ( id int, color char(12), name char(12), count int ) insert into maxthings values ( 1, "blue", "sam", 1) insert into maxthings values ( 2, "red", "bob", 5) insert into maxthings values ( 3, "green", "al", 3) insert into maxthings values ( 4, "orange", "joe", 2) insert into maxthings values ( 5, "orange", "joe", 3) insert into maxthings values ( 6, "orange", "joe", 1) this query using the SUM aggregate gets the right answer: SELECT id,color FROM maxthings m group by m.color having sum(count) > 2 however this query using the MAX aggregate doesn't return anything for the group of "orange" rows: SELECT id,color FROM maxthings m group by m.color having id = max(id) and if you add another row so that green has two values: insert into maxthings values ( 7, "green", "al", 5) then the "green" row disappears from the result. The MAX aggregate clearly has some issues. While its certainly possible to query out the max value simply using SELECT MAX(field) and skipping the HAVING entirely, I should think that a failure to execute any SQL command (even a somewhat esoteric one) would at least merit the status of a bug. When the bug causes a crash, at least you know something is up, but when it has the potential for silently returning the wrong answer, that seems like a concern to me.
[14 Apr 2006 15:39]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/4965
[14 Apr 2006 15:44]
Evgeny Potemkin
The SQL standard doesn't allow to use in HAVING clause fields that is not found in GROUP BY clause and not enclosed in any aggregate function in the HAVING clause. However, mysql allows using of such fields to simplify users calculations. This extension assume that the non-grouped fields will have the same group-wise values. Otherwise, the result will be unpredictable. The GROUP BY clause have the similar extension. You can read about it here http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-fields.html. I think that the possibly unpredictable result of using this HAVING extension should be explicitly noted somewhere in the manual.
[20 Apr 2006 21:53]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/5231
[24 Apr 2006 19:35]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/5423
[26 Apr 2006 18:46]
Evgeny Potemkin
Fixed in 5.0.22, cset 1.2056
[10 May 2006 18:51]
Paul DuBois
Noted in 5.0.22, 5.1.10 changelogs. The <literal>ONLY_FULL_GROUP_BY</literal> SQL mode now also applies to the <literal>HAVING</literal> clause. That is, columns not named in the <literal>GROUP BY</literal> clause cannot be used in the <literal>HAVING</literal> clause if not used in an aggregate function. Also revised this section to note that the MySQL extension applies to HAVING: http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-fields.html
[30 Sep 2007 13:02]
George Jara
I upgraded to "mysql Ver 14.12 Distrib 5.0.45, for Win32 (ia32)" and I still have the problem with max aggregate function under having clause, which return no records. This is the statement I am using: select value,datetime1 from myTable where datetime1 between '2007-09-17 00:00:00' and '2007-09-18 00:00:00' having max(datetime1)=datetime1; Result: 0 rows fetched. I'm trying to get the value for the last occurence of datetime1. With min(datetime1) it works perfect. Please note that if do not add datetime1 on selected columns, I get "Unknown column 'datetime1' in 'having clause'" error. It should be solved for this version. sql-mode variable is set to "STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
[22 Apr 2008 3:55]
Hrishikesh Date
I still see this issue in version 5.0.51a-co
[24 Sep 2008 18:36]
Alexander Vushkan
The issue is still in place even in 5.0.67.
[25 Jun 2009 21:00]
Paul Lin
issue still exist in 5.1.33
[10 Mar 2010 2:15]
jiang yongyuan
issus still in 6.0.11-alpha
[17 Mar 2010 15:55]
Sheeri Cabral
Why is this bug still closed when several people have noted it in versions > 5.0.21?
[3 Mar 2011 18:21]
eded eded
Maybe this can be an workaround : SELECT MAX(CASE WHEN @price<=price THEN CONCAT(@price:=price,@article:=article,@dealer:=dealer) ELSE 0 END) AS dummy, MAX(@article), MAX(@dealer), MAX(@price) FROM shop, (SELECT @article:=0) r , (SELECT @dealer:=0) r2, (SELECT @price:=0) r3 GROUP BY @price:=-10, @article:='', @dealer:=''; Using user-defined variables to store the most-expansive item related data in the same query.
[11 Jan 2012 22:10]
Guilhem Bichot
About the query in: "[30 Sep 2007 13:02] George Jara": select value,datetime1 from myTable where datetime1 between '2007-09-17 00:00:00' and '2007-09-18 00:00:00' having max(datetime1)=datetime1; There is a MAX(). As long as there's a MAX() there is aggregation. So what first happens is that the rows of myTable, after applying WHERE, are aggregated and a single row is produced; what value is taken for 'value' and 'datetime' for this row is random, it cannot be anything else. Then, HAVING compares this random datetime1 with the MAX(). Another justification for aggregation is that there is HAVING and no GROUP BY. The SQL standard says that this implies aggregation into a single "row. Values of 'value' and 'datetime' for this row are impossible to define (what value to prefer). What you want is probably: select value,datetime1 from myTable where datetime1 between '2007-09-17 00:00:00' and '2007-09-18 00:00:00' and datetime1=(select max(datetime1) from myTable));