3

The following code:

SELECT JaguarStartupTime, CPU, AmountOfRam, UpdatedOn, *
FROM dbo.MachineConfiguration
WHERE ServerName = 'WashingtonDC01'
AND UpdatedOn > '11/21/2012'
ORDER BY JaguarStartupTime DESC

results in an error: Ambiguous column name 'JaguarStartupTime'.

However, removing the ORDER BY makes it work. In addition, prefixing the ORDER BY clause with the table, like below, makes it work too:

SELECT JaguarStartupTime, CPU, AmountOfRam, UpdatedOn, *
FROM dbo.MachineConfiguration
WHERE ServerName = 'WashingtonDC01'
AND UpdatedOn > '11/21/2012'
ORDER BY dbo.MachineConfiguration.JaguarStartupTime DESC

This never made sense to me. Can someone explain?

AngryHacker
  • 59,598
  • 102
  • 325
  • 594

2 Answers2

8

Because the query includes * (all columns) in the SELECT clause, which also includes the column JaguarStartupTime.

In Layman's terms: So in the retrieval of the results, the column shows up twice, and then when the server tries to apply the sort order, it's not sure which column you are referring to.

Personally, I'd change the query to eliminate the use of * in the query, even if it means listing a long list of column names. It's best practice, and it will avoid this issue.


As for why it works when prefixed, I found this in the MSDN documentation:

In SQL Server, qualified column names and aliases are resolved to columns listed in the FROM clause. If order_by_expression is not qualified, the value must be unique among all columns listed in the SELECT statement.

This is simply part of the DB engine's underlying mechanism for translating SQL statements into the execution plan.

Community
  • 1
  • 1
David
  • 72,686
  • 18
  • 132
  • 173
  • Argh! You were faster! ;-) Deleted my answer, and +1. – Ken White Nov 26 '12 at 19:31
  • 1
    The server knows that it's the same column. For instance, if I add JaguarStartupTime to the WHERE clause, it happily filters on it, despite there being 2 identical columns. – AngryHacker Nov 26 '12 at 19:37
  • 1
    @AngryHacker - `WHERE` is processed after `FROM` but before `SELECT`. `ORDER` occurs after `SELECT`. (All of these orders are "as if" - the engine is free to re-order these operations, so long as the results are the same) – Damien_The_Unbeliever Nov 26 '12 at 19:41
  • Thanks all, curiosity satisfied. – AngryHacker Nov 26 '12 at 19:44
  • Also you could just use Order By 1 ...or whatever number is the column position of the column you want to order by. I do this frequently when I'm writing some quick and dirty code, and have an * in there. – Sylvia Nov 27 '12 at 14:46
1

I agree that in the case in your question ORDER BY JaguarStartupTime is not really ambiguous as both projected columns in fact refer to the same underlying column.

In the general case however there is no guarantee that this will be true. As discussed in the response to this connect item. For example in the following query it is clearly ambiguous which one would be used.

SELECT JaguarStartupTime,
       CPU AS JaguarStartupTime
FROM   dbo.MachineConfiguration
ORDER  BY JaguarStartupTime DESC 

For syntax validation purposes SQL Server does not do any analysis of column names to determine whether they are really ambiguous or not. When ordering by some_name that is present in the list of projected column names the some_name must be unique. This is as per the ANSI spec

If a <sort specification> contains a <column name>, then T shall contain exactly one column with that <column name> and the <sort specification> identifies that column.

Qualifying the column name with the table name ensures to SQL Server that you are ordering by a source column name rather than a projected column name so it allows it.

SELECT name, name 
FROM master..spt_values v1
ORDER BY v1.name

Additionally the following query is allowed.

select name, name 
FROM master..spt_values v1
ORDER BY name + ''

The reason why this is not ambiguous is because column aliases in an ORDER BY clause can only be used by themselves rather than in an expression so in the above query name can not be interpreted as an alias and must be interpreted as ordering by v1.name.

Martin Smith
  • 438,706
  • 87
  • 741
  • 845