views:

205

answers:

6

In a list of countries that need to be displayed in an alphabetical order, you need to place United States at the top of the list. How will do you this?

I answered by saying that I will have a table structure in such a way that the US is at id-0. The rest of the countries are listed in their alphabetical order.

So when I fetch from the table, I will do a "SELECT CountryName from tableOfCountries ORDER by ID"

I am not sure if the interviewer wanted to hear this. So I suggested another option of populating a country array with the US as the first element. Then the rest of the elements will be populated from the resultset of the query.

"SELECT CountryName FROM tableOfCountries WHERE countryName != 'US' ORDER by COUNTRY_NAME".

This will ensure that the US does not get selected twice.

The interviewer wasn't satisfied with this option either. So he asked me if I had any other option in mind. Then I said a text file on the webserver with the list of values.

Do you have any other options that you can think of?

+2  A: 

Maybe:

select name from countries
order by case when name = 'US' then 1 else 2 end, name;
Tony Andrews
+8  A: 

Generally something like:

SELECT 
    CountryName 

from tableOfCountries 

ORDER by 
    (case when CountryName = 'US' then 0 
     else 1 end) asc, CountryName asc
Adam Robinson
I wouldn't base the case statement on CountryName. What if later you want to change the name to 'United States' instead. Can you be sure to remember to change it in the case statement?
kevev22
@kevev22: Then base it off of the primary key, or assume that the name won't change. Yes, it's more brittle than modifying the actual table to store the value, but this approach requires no change to the table structure (which may or may not be an issue).
Adam Robinson
@kevev22: Additionally, this approach also gives you the flexibility to have different "default" values in different circumstances (say, it defaults to the user's home country instead of US). This seems as likely to happen as it would be for the global default country or countries to change.
Adam Robinson
@Adam: We could just as easily add that functionality into my solution, and still not hard code values into the order by clause.
kevev22
+8  A: 

Have another int column in the country table called precedence.

Assign United States a precedence greater than 1 and leave all other countries at 0.

Your SQL would then look like:

select Name from countries
order by precedence desc, name asc

This will allow you to scale this later if need be.

kevev22
What would be the benefit of adding the field now rather than if it's needed later (which seems a bit unlikely)?
Adam Robinson
@Adam: why do you think it's unlikely? If the OP's customer base expands so that other countries are major customers as well, then one might want to put those countries at the top of the list too. e.g. I often see drop-downs with several countries ranked on top, e.g. United States, Canada, United Kingdom, France, Germany, and then only after that are all other countries ordered alphabetically.
Ether
@Ether: I think it's unlikely to be a consideration in the short term. If there's no benefit to adding the column now versus later, then it adding it before it's needed is over-engineering (however slight it might be).
Adam Robinson
@Adam: I think in this case the added robustness more than compensates for the small extra effort to do it this way.
kevev22
@kevev22: You're assuming that adding a column to a table requires "small extra effort." Obviously, in terms of DDL, it's a simple operation and isn't likely to have much impact on anything, but many organizations have tedious processes in place when dealing with schema changes. It may not, indeed, be a "small extra effort". And, while it may be more robust, robustness is only a benefit if it's useful. When it isn't, then it's just fluff, over-engineering, bloat, etc.
Adam Robinson
I guess you're both right, but the danger with delaying the more robust change until later is it invites creep -- I can see some engineer modifying Adam's query to use 2 countries, then 3... rather than modifying the schema. If one makes the change now, then all subsequent country additions are trivial.
Ether
@Adam: You make a good point. As with every decision you have to weigh the cost with the benefit. But there is sometimes a fine line between over-engineering and engineering a scalable solution.
kevev22
+3  A: 

I certainly wouldn't abuse ID that way if I could avoid it.

One could give priorities to countries and then:

select isoCode, name from countries order by priority desc, name

Alternatively, why have it at the top? I'd suggest changing the logic so that they remained in alphabetical order, but US was the default selection until changed.

Jon Hanna
A: 

If this is in C#, disregarding how the data comes back from the server, placing them in a specific type and implementing IComparable on the given type. The drop down will then hold them accordingly as you can specify in the CompareTo method that the US type is the "greater" of the other countries.

class Country : IComparable<Country>
{
    int IComparable<Country>.CompareTo(Country other)
    {
        <US logic>
        else
            return String.Compare(this.CountryName, other.CountryName);
    }
}

EDIT: Actually this is in C# based on the OP's tags. Why the focus on the back end for presentation is taking place is beyond me.

Aaron
Err, no. There are no databound controls that will automatically sort elements in a data source based upon a comparison result.
Adam Robinson
@Adam There is no reference anywhere that states these need to be databound. With this being the case, placing the objects in a sortable container will then make use of the IComparable implementation and do whatever is desired upon calling Sort(). Whatever is done with that collection after the fact doesn't matter; binding it to a ComboBox for instance. This is no different then doing this on the back end and pushing that collection upstream to the UI to be displayed in a given control. If we talk specific .NET technologies then you could also make use of a CollectionView.
Aaron
A: 

Another way to do it would be to get your list of states and then filter them into a dataview, excluding the default items. Then set the list control property AppendDataBoundItems to true. Add your items to the list control and then databind to the dataview.

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.appenddatabounditems.aspx

This will have the effect of not clearing your default values when the databind occurs.

Mike Cheel