16

The GROUP BY clause groups the rows, but it does not necessarily sort the results in any particular order. To change the order, use the ORDER BY clause, which follows the GROUP BY clause. The columns used in the ORDER BY clause must appear in the SELECT list, which is unlike the normal use of ORDER BY. [Oracle by Example, fourth Edition, page 274]

Why is that? Why does using GROUP BY influence the required columns in the SELECT clause?

Also, in the case where I do not use GROUP BY: Why would I want to ORDER BY some columns but then select only a subset of the columns?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • To answer your second question: maybe the column is strictly for ordering, like a `display_order` column. You don't care for it in the results but you want to order by it. – lc. Aug 29 '12 at 18:51

7 Answers7

7

Actually the statement is not entirely true as Dave Costa's example shows.

The Oracle documentation says that an expression can be used but the expression must be based on the columns in the selection list.

expr - expr orders rows based on their value for expr. The expression is based on columns in the select list or columns in the tables, views, or materialized views in the FROM clause. Source: Oracle® Database SQL Language Reference 11g Release 2 (11.2) E26088-01 September 2011. Page 19-33

From the the same work page 19-13 and 19-33 (Page 1355 and 1365 in the PDF)

enter image description here

enter image description here

http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10002.htm#SQLRF01702

http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10002.htm#i2171079

hol
  • 8,255
  • 5
  • 33
  • 59
7

The bold text from your quote is incorrect (it's probably an oversimplification that is true in many common use cases, but it is not strictly true as a requirement). For instance, this statement executes just fine, although AVG(val) is not in the select list:

WITH DATA AS (SELECT mod(LEVEL,3) grp, LEVEL val FROM dual CONNECT BY LEVEL < 100)
SELECT grp,MIN(val),MAX(val)
FROM DATA
GROUP BY grp
ORDER BY AVG(val)

The expressions in the ORDER BY clause simply have to be possible to evaluate in the context of the GROUP BY. For instance, ORDER BY val would not work in the above example, because the expression val does not have a distinct value for each row produced by the grouping.

As to your second question, you may care about the ordering but not about the value of the ordering expression. Excluding unneeded expressions from the select lists reduces the amount of data that must actually be sent from the server to the client.

Dave Costa
  • 47,262
  • 8
  • 56
  • 72
3

First:

The implementation of group by is one which creates a new resultset that differs in structure to the original from clause (table view or some joined tables). That resultset is defined by what is selected.

Not every SQL RDBMS has this restriction, though it is a always requirement that what is ordered by be either an aggregate function of the non-grouped columns (AVG, SUM, etc) or one of the columns grouped by, or functions upon more than one of those results (like adding two columns), because this is a logical requirement of the result of the grouping operation.

Second:

Because you only care about that column for the ordering. For example, you might have a list of the top selling singles without giving their sales (the NYT Bestsellers keeps some details of their data a secret, but do have a ranked list). Of course, you can get around this by just selecting that column and then not using it.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • Interesting. I think this is the only logical explanation. – lc. Aug 29 '12 at 19:01
  • But the restriction, as described in the question, doesn't actually exist. The restriction that you describe in your answer is more accurate. – Dave Costa Aug 29 '12 at 19:07
  • @DaveCosta do you have an oracle installation on hand to double-check that the book is wrong? If I had to bet I'd place money on it being wrong - I see no good reason for insisting that the full resultset produced by grouping be selected into the final resultset, any more than e.g. JOIN would - but knowing with certainty is always nice. – Jon Hanna Aug 29 '12 at 19:09
  • 1
    @JonHanna -- yeah, I tested it before I posted anything. See my answer for just one example. – Dave Costa Aug 29 '12 at 19:12
  • 1
    @DaveCosta Nice one. I feel like all is well with the world again :) – Jon Hanna Aug 29 '12 at 19:15
2

The data is aggregated before it is sorted for the ORDER BY.

If you try to order by any other column (that is not in the group by list or an aggregation function), what value would be used? There is no single value to use for ordering.

I believe that you can use combinations of the values for sorting. So you can say:

order by a+b

If a and b are in the group by. You just cannot introduce columns not mentioned in the SELECT. I believe you can use aggregation functions not mentioned in the SELECT, however.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • I'm not sure I still understand why `SELECT a, SUM(c) FROM xx GROUP BY a, b ORDER BY a+b` would be invalid? – lc. Aug 29 '12 at 18:57
  • @lc . . . You can do that in most databases. Does it really not work in Oracle? – Gordon Linoff Aug 29 '12 at 19:05
  • It's not the inclusion in the SELECT list that matters, it's the inclusion in the GROUP BY. `WITH DATA AS (SELECT mod(LEVEL,3) grp, LEVEL val FROM dual CONNECT BY LEVEL < 100) SELECT MIN(val),MAX(val) FROM DATA GROUP BY grp ORDER BY grp` -- grp is not in the select list but can still be referenced in the order-by. – Dave Costa Aug 29 '12 at 19:05
  • Yes, I'm surprised by that too. A group by inherently does a select into a resultset for everything grouped by and aggregated, but I'm surprised by the idea that one has to select that into the final resultset. – Jon Hanna Aug 29 '12 at 19:07
  • @GordonLinoff I'm not sure. I know you can do that in most databases, but the OP's quote suggests that you *can't* in Oracle for some reason, thus the question of why... – lc. Aug 29 '12 at 19:07
  • @DaveCosta Yeah, I'm quite convinced of that now. Odd though. Maybe in an old version of Oracle it used to be that way? – lc. Aug 29 '12 at 19:14
  • @lc. . . . This is pure speculation, but I suspect the documentation is and always has been wrong. Jon Hanna makes a good point. However, the keys for the group by are also carried along with the data. In a sense, Oracle would have to intentionally ignore them for the documentation to be correct. – Gordon Linoff Aug 29 '12 at 19:33
  • The quote isn't from what I'd consider Oracle documentation, although it may be from other materials published by Oracle. The Oracle SQL Language Reference is accurate: If you specify a group_by_clause in the same statement, then this order_by_clause is restricted to the following expressions: Constants Aggregate functions Analytic functions The functions USER, UID, and SYSDATE Expressions identical to those in the group_by_clause Expressions comprising the preceding expressions that evaluate to the same value for all rows in a group – Dave Costa Aug 29 '12 at 20:34
1

Sample table

sample.grades
Name   Grade    Score
Adam   A        95
Bob    A        97
Charlie C       75

First Query using GROUP BY

Select grade, count(Grade) from sample.grades GROUP BY Grade

Output

Grade Count
A     2
C     1

Second Query using order by

select Name, score from sample grades order by score

Output

Bob    A        97
Adam   A        95
Charlie C       75

Third Query using GROUP BY and ordering

Select grade, count(Grade) from sample.grades GROUP BY Grade desc

Output

Grade Count
A     2
C     1

Once you start using things like Count, you must have group by. You can use them together, but they have very different uses, as I hope the examples clearly show.

To try and answer the question, why does group by effect the items in the select section, because that is what group by is meant to do. You can't do the count of a column if you do not group by that column.

Second question, why would you want to order by but not select all the columns? If I want to order by the score, but do not care about the actual grade or even the score I might do

select name from sample.grades order by score

Output

Name
Bob
Adam
Charlie
Dan Ciborowski - MSFT
  • 6,807
  • 10
  • 53
  • 88
0

Which results do you expect to see ordering by columns not listed in the select list and not participated in group by clause? at any case all kind of sort by non-mentioned in SELECT list columns will be omitted so Oracle guys added the restriction correctly.

with c as (
select 1 id, 2 value from dual
union all
select 1 id, 3 value from dual
union all
select 2 id, 3 value from dual
)
select id
from c
group by id
order by count(*) desc
Alexander Tokarev
  • 1,000
  • 7
  • 16
  • But what would be wrong with `ORDER BY COUNT(*)` but not actually returning `COUNT(*)` in the result set? – lc. Aug 29 '12 at 18:53
  • 1
    And actually, the Oracle guys didn't add this restriction. Try it. – Dave Costa Aug 29 '12 at 18:57
  • To Dave: just add to my query order by value and you get ORA-00979 so they do add the restriction – Alexander Tokarev Aug 29 '12 at 19:02
  • @AlexanderTokarev No, that is a different restriction (column not in group by or aggregate). The OP is referring to a order by clause not in select as my earlier comment asks. Interesting though that `ORDER BY COUNT(*)` does work - this contradicts the OP's quote! – lc. Aug 29 '12 at 19:04
  • 1
    The documentation is implemented by humans which could make errors :). It is perfect example of it. – Alexander Tokarev Aug 29 '12 at 19:11
0

Here my inderstanding

"The GROUP BY clause groups the rows, but it does not necessarily sort the results in any particular order."

-> you can use Group by without order by

"To change the order, use the ORDER BY clause, which follows the GROUP BY clause."

-> the rows are selected by defaut with primary key, and if you add order by you must add after group by

"The columns used in the ORDER BY clause must appear in the SELECT list, which is unlike the normal use of ORDER BY."

Aghilas Yakoub
  • 28,516
  • 5
  • 46
  • 51