4

I've got the table:

SELECT * FROM shop;

+---------+--------+------
| article | dealer | price
+---------+--------+------
|    0001 | A      |  3.45
|    0001 | B      |  3.99
|    0002 | A      | 10.99
|    0003 | B      |  1.45
|    0003 | C      |  1.69
|    0003 | D      |  1.25
|    0004 | D      | 19.95
+---------+--------+------
7 rows in set (0.20 sec)

And I want to get - for each article - the dealer or dealers with the most expensive price.

Could anyone tell me why this doesn’t work?

SELECT article, dealer, MAX(price) FROM shop GROUP BY(article);

For this query, I get the following result-set;

+---------+--------+------------+
| article | dealer | MAX(price) |
+---------+--------+------------+
|    0001 | A      |       3.99 |
|    0002 | A      |      10.99 |
|    0003 | B      |       1.69 |
|    0004 | D      |      19.95 |
+---------+--------+------------+
4 rows in set (0.03 sec)

Although the max prices are correct, I got the wrong dealers for some articles.

Braiam
  • 1
  • 11
  • 47
  • 78
karakays
  • 3,643
  • 3
  • 20
  • 14

5 Answers5

4

According to your question it seems that you have already read the article about group-wise maximum of a certain column, however you just don't understand why the method you mentioned does not work as you expect.

Let's imagine a query like this:

SELECT article, dealer, MAX(price), MIN(price) 
FROM shop 
GROUP BY article

What value of a dealer do you expect?

I think this answers your question.

Karolis
  • 9,396
  • 29
  • 38
1

Standard SQL would reject your query because you can not SELECT non-aggregate fields that are not part of the GROUP BY clause in an aggregate query.

You're using a MySQL extension of SQL described here:

MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
themel
  • 8,825
  • 2
  • 32
  • 31
  • why MYSQL creating new rules which are not followed by Standard SQL – rahularyansharma Sep 29 '11 at 08:53
  • @rahularyansharma MySQL says: _you can use this feature to get better performance by avoiding unnecessary column sorting and grouping_. – Karolis Sep 29 '11 at 09:06
  • so why they say indeterminate results dear .its confusing for a user that he dont know what the result come for a TSQl he writes . IS it ok ????? – rahularyansharma Sep 29 '11 at 09:08
  • 1
    @rahularyansharma This feature is useful from the performance perspective when it is already known that all values in every group are the same. I often use this feature. – Karolis Sep 29 '11 at 09:16
  • @Karolis will u please mention here how it performs performance optimization and this type of optimization in price of confusion for user is ok . and if values in group are not same then which row they pick ?any idea abt that dear – rahularyansharma Sep 29 '11 at 09:22
  • 1
    @rahularyansharma `group by` clause internally requires sorting of all columns mentioned in the clause. The less columns mentioned in `group by` clause the less sorting is needed. When you know that values are not the same in a group then you should not use this feature. – Karolis Sep 29 '11 at 09:37
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/3889/discussion-between-rahularyansharma-and-karolis) – rahularyansharma Sep 29 '11 at 09:41
  • 1
    @rahularyansharma: "why MYSQL creating new rules which are not followed by Standard SQL" All the big DBMSs have their own flavours and extensions; otherwise why would there ever be more than one of them? – Lightness Races in Orbit Sep 29 '11 at 09:56
  • 1
    @Tomalak should they override the basic of Standard SQl ? if they make extension they should be follow basics . – rahularyansharma Sep 29 '11 at 10:06
  • @rahularyansharma: Whilst it's quite entertaining watching you try to tell off MySQL, extending language specifications is nothing new. In fact the only thing that they've "overridden" is the lack of this ability in original SQL, which is kind of unavoidable if you're going to add functionality. – Lightness Races in Orbit Sep 29 '11 at 10:09
  • @TomalakGeret'kal ok then my simple question is why not MS Sql server do this yet – rahularyansharma Sep 29 '11 at 10:15
  • 1
    @rahularyansharma: They chose not to implement this extension. Why? You'd have to ask them as I am not a psychic... – Lightness Races in Orbit Sep 29 '11 at 10:24
  • @TomalakGeret'kal because this is wrong my dear .you can not change the basics in cost of some performance .and i am sure i see some good results as i posted it stackoverflow.com http://stackoverflow.com/questions/7594865/mysql-extends-in-such-a-manner-that-rules-are-not-followed-by-sql-standards . some have votes to close i dont know why ? but it is very interesting topic to ..... – rahularyansharma Sep 29 '11 at 10:29
  • 1
    @rahularyansharma: I really have no idea what you're talking about now. No "basics" have been "changed". And please don't call me "dear"; you're not my mother. – Lightness Races in Orbit Sep 29 '11 at 10:35
  • ***"Standard SQL would reject your query because you can not SELECT non-aggregate fields that are not part of the GROUP BY clause in an aggregate query"*** This is plainly wrong. – ypercubeᵀᴹ Sep 29 '11 at 10:52
  • @ypercube - is it? I'd appreciate a citation. – themel Sep 30 '11 at 06:48
  • It's wrong from SQL-2003 standards and beyond. See my answer here: http://stackoverflow.com/questions/7594865/why-does-mysql-add-a-feature-that-conflicts-with-sql-standards/7596265#7596265 – ypercubeᵀᴹ Sep 30 '11 at 08:34
0

I just tumbled over this question and wonder why noone comes to idea to join the table with itself as described in certain tutorials (see links below).

So I'd suggest the following solution:

Select A.* 
From      shop As A 
Left Join shop As B On  A.article
                     =  B.Article 
                    AND A.price 
                      < B.price 
Where B.price Is Null;

The magic is obvious: join the table with itself and link any records in it to any other record having a higher price. From those, grab only those having NO linked record with a higher price (for these records are the ones with the highest price).

As far as I have experienced, this solution is even the best regarding its performance.

This part of the MySQL documentation and/or this very interesting article by Jan Kneschke might be helpful — enjoy!

Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
IBeRKa
  • 1
  • 1
0

This does not work, because if you use group by, you can not use the individual fields of the original rows (except for the field you are grouping on). The correct way to do this, is to make an inner/nested query to select the dealer, suck as this (I haven't tested it, so it might be slightly off):

SELECT article, MAX(price) as maxPrice, (SELECT dealer FROM shop AS s2 WHERE s2.article = s1.article AND s2.price = maxPrice) AS expensiveDealer FROM shop AS s1 GROUP BY(article);

Bruce
  • 1,542
  • 13
  • 17
Thirler
  • 20,239
  • 14
  • 63
  • 92
  • 2
    Your nested SQL should be "SELECT dealer" not "SELECT price" - I have changed it. I haven't tested the full statement though. – Bruce Sep 29 '11 at 08:39
0

Here you go:

SELECT article, dealer, price
FROM (SELECT article, dealer, price
      FROM shop
      ORDER BY price DESC) AS h
GROUP BY article

This solution doesn't even require a MAX() function. :)

Note: This solution doesn't work with ONLY_FULL_GROUP_BY active and only works in MySQL. This solution is to a certain extent unsupported due to lack of documentation confirming this behavior. It works well for me and has always worked well for me however.

This method still works on the latest MySQL on sqlfiddle.

Robin Castlin
  • 10,956
  • 1
  • 28
  • 44
  • This is thoroughly wrong. Your fiddle returns only 1 row, when it needs to return 1 row per type. Moreover, there is only one row per type in the table, so even if it was to return one row per group, it wouldn't tell us anything about how it selected from that group. – Olsgaard Feb 10 '23 at 08:02