tags:

views:

259

answers:

4

I have a small problem. I'm populating a select tag with results from a SQL database. What I would like to have is the last one added as the top entry and the rest sorted alphabetically.

So it would return:

*----------*-------------*
developerID|developerName
*----------*-------------*
| 40       | ZZZ Dev     |
| 39       | A Dev       |
| 38       | Be New Dev  |
*----------*-------------*

Currently it just selects all the entries in descending order:

"SELECT developerName, developerID FROM developer ORDER BY developerID DESC"

Which is fine, but not as usable as I would like.

Is what I want possible using pure MySQL?

A: 
SELECT developerName, developerID 
  FROM developer 
  ORDER BY developerID = {last_used},developerID DESC

Or some variant there of. The idea being to do a two part sort, with the first segment pulling out the last one used.

-- MarkusQ

On edit: reversed the sense (added not) 'cause you want it at the top.

Second edit, reverted my first edit in response to your edit of the question.

MarkusQ
Your sort is giving descending order of developerID; the request for was alphabetic, so should be on ascending order of developerName, shouldn't it? The 'manufactured' column is part of the answer; you're using a boolean and assuming (possibly correctly) that TRUE orders before FALSE.
Jonathan Leffler
I went through some editing flail on this as he edited the question and then gave up. In MySQL true == 1 and false == 0, so something of this form should get him what he wants, but the details depend on what exactly he wants.
MarkusQ
Don't worry about the edits, that's just me realising that I posted too little initial information. Human error. :)
different
+7  A: 

Assuming the column defining when the developer was added is developerAdded (a timestamp of some sort):

SELECT developerName, developerID, 1 AS ordering
    FROM developer
    WHERE developerAdded =  (SELECT MAX(developerAdded)
                                FROM developer)
UNION
SELECT developerName, developerID, 2 AS ordering
    FROM developer
    WHERE developerAdded != (SELECT MAX(developerAdded)
                                FROM developer)
ORDER BY ordering, developername;

If there's some other magic way to determine the most recently added developer (e.g. maximum developerID), adjust the sub-queries accordingly.

Note that this query works OK even if several developers satisfy the 'most recently added' criterion; they appear in alphabetic order before the developers who've been around longer.


Since the most recently added developer has the maximum developerID, the revised query should be:

SELECT developerName, developerID, 1 AS ordering
    FROM developer
    WHERE developerID =  (SELECT MAX(developerID) FROM developer)
UNION
SELECT developerName, developerID, 2 AS ordering
    FROM developer
    WHERE developerID != (SELECT MAX(developerID) FROM developer)
ORDER BY ordering, developername;
Jonathan Leffler
Perfect. The most recently added developer is the max developerID, no real need to store a date there. But that returns exactly what I wanted. Thanks very much Jonathan. :)
different
+2  A: 

I think the best way to do this is just with two queries. Display the most recent item separate from the regular alphabetical list, where it will also appear (so it's shown twice). This is easy to do and arguably more intuitive and usable anyway.

Otherwise, if you're really insistent on doing it your way and with a single SQL query, you can use UNION ALL and INTERSECT or EXCEPT to cook something up. But MySQL doesn't preserve any sort of order in the results of a UNION (see http://dev.mysql.com/doc/refman/5.1/en/union.html), and so such a query is likely to get ugly fast.

kquinn
You just hold MySQL's hand to the fire and make it preserve the order - see my answer.
Jonathan Leffler
Right, you can do that. But I still think the separate solution is easier *and* produces a more intuitive final result anyway. Having a row displayed twice isn't a big deal, especially if the most recent row is marked as special in some way (which it is, so it should be so marked).
kquinn
I would have to disagree - listing things twice that should be listed once is a big issue, maybe not in this case, but in general. Which is more 'intuitive' depends on your intuition - mine appears to disagree with yours.
Jonathan Leffler
+1  A: 

I would recommend against trying to alter the sort order of the items in your list, as that changes the "expected behavior" your users will have about the list.

If the most common use of that page usually deals the "last added" name, you could make that the "default" selection in the list. So when the page comes up, the last added entry is already selected in the list - but if they open the list all the entries are still there alphabetically and it will behave as they expect.

That way your query stays simple, but you achieve your "usability" goal as well.

Ron

Ron Savage
That's a good idea, didn't think about it that way. But, the only user using this is myself.
different
If your list is consistently presented a certain way, people (just yourself) get used to what is there. It is perfectly reasonable to want the users in the order requested (not a common requirement, but perfectly reasonable).
Jonathan Leffler