tags:

views:

30

answers:

3

I just came across this database query and wonder what exactly this query does..Please clarify ..

select * from tablename order by priority='High' DESC, priority='Medium' DESC, priority='Low" DESC;
A: 

Looks like it'll order the priority by High, Medium then Low.

Because if the order by clause was just priority DESC then it would do it alphabetical, which would give

Medium Low High

Fermin
A: 

It basically lists all fields from the table "tablename" and ordered by priority High, Medium, Low. So High appears first in the list, then Medium, and then finally Low

i.e.

* High
* High
* High
* Medium
* Medium
* Low

Where * is the rest of the fields in the table

Chris
A: 

Others have already explained what id does (High comes first, then Medium, then Low). I'll just add a few words about WHY that is so.

The reason is that the result of a comparison in MySQL is an integer - 1 if it's true, 0 if it's false. And you can sort by integers, so this construct works. I'm not sure this would fly on other RDBMS though.

Added: OK, a more detailed explanation. First of all, let's start with how ORDER BY works.

ORDER BY takes a comma-separated list of arguments which it evalutes for every row. Then it sorts by these arguments. So, for example, let's take the classical example:

SELECT * from MyTable ORDER BY a, b, c desc

What ORDER BY does in this case, is that it gets the full result set in memory somewhere, and for every row it evaluates the values of a, b and c. Then it sorts it all using some standard sorting algorithm (such as quicksort). When it needs to compare two rows to find out which one comes first, it first compares the values of a for both rows; if those are equal, it compares the values of b; and, if those are equal too, it finally compares the values of c. Pretty simple, right? It's what you would do too.

OK, now let's consider something trickier. Take this:

SELECT * from MyTable ORDER BY a+b, c-d

This is basically the same thing, except that before all the sorting, ORDER BY takes every row and calculates a+b and c-d and stores the results in invisible columns that it creates just for sorting. Then it just compares those values like in the previous case. In essence, ORDER BY creates a table like this:

+-------------------+-----+-----+-----+-----+-------+-------+
| Some columns here |  A  |  B  |  C  |  D  |  A+B  |  C-D  |
+-------------------+-----+-----+-----+-----+-------+-------+
|                   |  1  |  2  |  3  |  4  |   3   |   -1  |
|                   |  8  |  7  |  6  |  5  |   15  |   1   |
|                   | ... | ... | ... | ... |  ...  |  ...  |
+-------------------+-----+-----+-----+-----+-------+-------+

And then sorts the whole thing by the last two columns, which it discards afterwards. You don't even see them it your result set.

OK, something even weirder:

SELECT * from MyTable ORDER BY CASE WHEN a=b THEN c ELSE D END

Again - before sorting is performed, ORDER BY will go through each row, calculate the value of the expression CASE WHEN a=b THEN c ELSE D END and store it in an invisible column. This expression will always evaluate to some value, or you get an exception. Then it just sorts by that column which contains simple values, not just a fancy formula.

+-------------------+-----+-----+-----+-----+-----------------------------------+
| Some columns here |  A  |  B  |  C  |  D  |  CASE WHEN a=b THEN c ELSE D END  |
+-------------------+-----+-----+-----+-----+-----------------------------------+
|                   |  1  |  2  |  3  |  4  |                 4                 |
|                   |  3  |  3  |  6  |  5  |                 6                 |
|                   | ... | ... | ... | ... |                ...                |
+-------------------+-----+-----+-----+-----+-----------------------------------+

Hopefully you are now comfortable with this part. If not, re-read it or ask for more examples.

Next thing is the boolean expressions. Or rather the boolean type, which for MySQL happens to be an integer. In other words SELECT 2>3 will return 0 and SELECT 2<3 will return 1. That's just it. The boolean type is an integer. And you can do integer stuff with it too. Like SELECT (2<3)+5 will return 6.

OK, now let's put all this together. Let's take your query:

select * from tablename order by priority='High' DESC, priority='Medium' DESC, priority='Low" DESC;

What happens is that ORDER BY sees a table like this:

+-------------------+----------+-----------------+-------------------+----------------+
| Some columns here | priority | priority='High' | priority='Medium' | priority='Low' |
+-------------------+----------+-----------------+-------------------+----------------+
|                   | Low      |        0        |         0         |        1       |
|                   | High     |        1        |         0         |        0       |
|                   | Medium   |        0        |         1         |        0       |
|                   | Low      |        0        |         0         |        1       |
|                   | High     |        1        |         0         |        0       |
|                   | Low      |        0        |         0         |        1       |
|                   | Medium   |        0        |         1         |        0       |
|                   | High     |        1        |         0         |        0       |
|                   | Medium   |        0        |         1         |        0       |
|                   | Low      |        0        |         0         |        1       |
+-------------------+----------+-----------------+-------------------+----------------+

And it then sorts by the last three invisble columns which are discarded later.

Does it make sense now?

(P.S. In reality, of course, there are no invisible columns and the whole thing is made much trickier to get good speed, using indexes if possible and other stuff. However it is much easier to understand the process like this. It's not wrong either.)

Vilx-
On a side note, I found an interesting bug a few days ago which had to deal with the same construct. One developer had written `WHERE colA=15=colB` trying to check that both columns equalled 15. This backfired because `colA=15` was equal to 1 and the resulting comparison was equivalent to `WHERE colA=15 AND colB=1`. The funny thing is - this code had run in production for **years**, the particular line got executed at least once a day, but the bug surfaced just last week. Talk about lucky data!
Vilx-
thanks for this but i m not still comfortable with the query ..
Sachindra