• Easy today - what Hugo says is axiomatic.

    Hugo Kornelis (5/7/2013)


    Thanks! Good question.

    In addition to the explanation given: the restriction actually makes sense. Remember that, logically, the ORDER BY is performed *after* the SELECT. In the official ANSI standard, columns in the ORDER BY must always be in the SELECT clause. The fact that we usually can order by other columns is because, logically, SQL Server adds a hidden extra column in the SELECT, uses it for ordering, then doesn't disply it or return it to the client. (And I stress that this is "logically" - queries are not actually executed that way!). But with a SELECT DISTINCT, that is impossible. Adding the extra column before the DISTINCT would influence the results (the extra columns could make rows that are otherwise the same distinct to each other, and once removed the results would show duplicate rows in spite of the DISTINCT). And adding the extra column after the DISTINCT is impossible, since a single row after DISTINCT can correspond to multiple rows before DISTINCT.

    Or, yet another way to put it, suppose I have this data in a table called MyTable:

    Col1 | Col2

    -----+-----

    1 | a

    2 | b

    3 | a

    Now suppose I were allowed to execute this query:

    SELECT DISTINCT Col2

    FROM MyTable

    ORDER BY Col1;

    The resultset should contain an "a" and a "b". But in what order? The "b" comes from the row with Col1 = 2, but the "a' comes from two rows, with Col1 = 1 and Col1 = 3. Should the "a" go before or after the "b"? There is no possible answer for this - and that's why the query is illegal!

    Raghavendra Mudugal (5/7/2013)


    I guess, when we DISTINCT, it also sorts the data physically, so usage of additional ORDER BY is not needed

    WRONG!!!!!!

    This may or may not work correctly, but you have no guarantee.

    The optimizer had different ways to implement a DISTINCT. One of them is a "Distinct sort" - where rows are sorted and duplicate are removed. That would produce results in the specified output - though the optimizer could decide to reverse the order of the columns. Another way would be to convert the DISTINCT to an aggregate - remember that there is no difference at all between "SELECT DISTINCT Col1 FROM MyTable" and "SELECT Col1 FROM MyTable GROUP BY MyCol", and the optimizer knows that. If the aggregeate is implemented with a stream aggregate operator. you may still be okay (though, again, the order of the columns if more than one is used can be changed to match an existing index and avoid a sort step). But if a hash aggregate operator is used, you're completely hosed.

    And then, with a large enough table, you can get a parallel plan, where each individual stream might or might not have the rows in order, but the order is not retained when gathering streams. Or, with a complex query, the optimizer might decide to push down the distinct operator as far as possible to reduce the rows, and then reorder the results coming out of it for the rest, e.g. to facilitate a merge join, or as a byproduct of a hash join.

    When working with SQL Server, if you need guarantees about the order in which results will be returned - ALWAYS USE AN ORDER BY!!!!!

    Everything else means you rely on undocumented, and hence unguaranteed behaviour. A ticking timebomb!