Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What can an aggregate function do in the ORDER BY clause?

Lets say I have a plant table:

id fruit
1  banana
2  apple
3  orange

I can do these

SELECT * FROM plant ORDER BY id;
SELECT * FROM plant ORDER BY fruit DESC;

which does the obvious thing.

But I was bitten by this, what does this do?

SELECT * FROM plant ORDER BY SUM(id);
SELECT * FROM plant ORDER BY COUNT(fruit);
SELECT * FROM plant ORDER BY COUNT(*);
SELECT * FROM plant ORDER BY SUM(1) DESC;

All these return just the first row (which is with id = 1).

  1. What's happening underhood?
  2. What are the scenarios where aggregate function will come in handy in ORDER BY?
like image 214
nawfal Avatar asked Oct 27 '12 10:10

nawfal


People also ask

Can we use aggregate function in ORDER BY clause Oracle?

Aggregate functions can appear in select lists and in ORDER BY and HAVING clauses. They are commonly used with the GROUP BY clause in a SELECT statement, where Oracle Database divides the rows of a queried table or view into groups.

What does an aggregate function do?

An aggregate function performs a calculation on a set of values, and returns a single value. Except for COUNT(*) , aggregate functions ignore null values. Aggregate functions are often used with the GROUP BY clause of the SELECT statement.

What is use of ORDER BY clause?

The ORDER BY keyword is used to sort the result-set in ascending or descending order. The ORDER BY keyword sorts the records in ascending order by default. To sort the records in descending order, use the DESC keyword.

Can we use aggregate function in partition by?

When we want to do an aggregation on a specific column, we can apply PARTITION BY clause with the OVER clause. Let's look at the example below to see how the dataset has been transformed. In the example, I want to calculate the total and average amount of money that each function brings for the trip.


2 Answers

Your results are more clear if you actually select the aggregate values instead of columns from the table:

SELECT SUM(id) FROM plant ORDER BY SUM(id)

This will return the sum of all id's. This is of course a useless example because the aggregation will always create only one row, hence no need for ordering. The reason you get a row qith columns in your query is because MySQL picks one row, not at random but not deterministic either. It just so happens that it is the first column in the table in your case, but others may get another row depending on storage engine, primary keys and so on. Aggregation only in the ORDER BY clause is thus not very useful.

What you usually want to do is grouping by a certain field and then order the result set in some way:

SELECT fruit, COUNT(*)
FROM plant
GROUP BY fruit
ORDER BY COUNT(*)

Now that's a more interesting query! This will give you one row for each fruit together with the total count for that fruit. Try adding some more apples and the ordering will actually start making sense:

Complete table:

+----+--------+
| id | fruit  |
+----+--------+
|  1 | banana |
|  2 | apple  |
|  3 | orange |
|  4 | apple  |
|  5 | apple  |
|  6 | banana |
+----+--------+

The query above:

+--------+----------+
| fruit  | COUNT(*) |
+--------+----------+
| orange |        1 |
| banana |        2 |
| apple  |        3 |
+--------+----------+
like image 130
Emil Vikström Avatar answered Oct 13 '22 12:10

Emil Vikström


All these queries will all give you a syntax error on any SQL platform that complies with SQL standards.

SELECT * FROM plant ORDER BY SUM(id);
SELECT * FROM plant ORDER BY COUNT(fruit);
SELECT * FROM plant ORDER BY COUNT(*);
SELECT * FROM plant ORDER BY SUM(1) DESC;

On PostgreSQL, for example, all those queries will raise the same error.

ERROR: column "plant.id" must appear in the GROUP BY clause or be used in an aggregate function

That means you're using a domain aggregate function without using GROUP BY. SQL Server and Oracle return similar error messages.

MySQL's GROUP BY is known to be broken in several respects, at least as far as standard behavior is concerned. But the queries you posted were a new broken behavior to me, so +1 for that.

Instead of trying to understand what it's doing under the hood, you're probably better off learning to write standard GROUP BY queries. MySQL will process standard GROUP BY statements correctly, as far as I know.

Earlier versions of MySQL docs warned you about GROUP BY and hidden columns. (I don't have a reference, but this text is cited all over the place.)

Do not use this feature if the columns you omit from the GROUP BY part are not constant in the group. The server is free to return any value from the group, so the results are indeterminate unless all values are the same.

More recent versions are a little different.

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.

Personally, I don't consider indeterminate a feature in SQL.

like image 29
Mike Sherrill 'Cat Recall' Avatar answered Oct 13 '22 14:10

Mike Sherrill 'Cat Recall'