tags:

views:

268

answers:

4

Hi All

It would be great if there was a POSITIVE answer to this question...

Is it possible to make an SQL selection based on an order of possible condition values.

Eg.

Rows
ID Type
2 Dog
2 Cat
4 Cat
5 Cat

As you can see the IDs of the 1st 2 rows are the same. So I would like to select 1 row per group in order of preference, therefore "Dog" first. If "Dog" doesn't exists, then select "Cat"

E.G.
SELECT ID, Type
FROM pets
WHERE Type = "Dog, Cat"
GROUP BY ID

Results would be...

ID Type
2 Dog
4 Cat
5 Cat

+1  A: 

I'm not sure what your "real" requirement is, but for your exmple you can use:

SELECT ID, Max(Type)
FROM pets
WHERE Type IN ('Dog', 'Cat')
GROUP BY ID

Notes:

  1. The IN clause is required only if you want to limit types. It may be removed if you want all the types included in the query.
  2. This query works if the ordering by which you prioritize the Types can be done using sorting, either alphabetically or numerically. If so, using Min or Max together with GROUP BY is the simplest and most efficient solution. If however your prioritization is based on some specific ordering, look-up table etc, you will need a different solution where you have a separate table containing the priorities and joined into the main query, as astander answered.
Roee Adler
+1, I think WHERE Type IN('Dog', 'Cat') is unnecessary. He gave it just for example
Svetlozar Angelov
What I meant was that 'Dog' would always be selected over 'Cat'. But if 'Dog' wasn't there, then 'Cat' would be selected.
Theo
This doesn't seem to address the OP's need to ensure a specific order of preference in which row is selected for duplicate id values. Theo, take a look at my answer for something which should address your needs.
Amber
A: 

If grouping (as in the answer above) is not the option take a look at ranking functions introduced in SQL Server 2005.

UserControl
+1  A: 

If you have another table which ranks your options in order by preference, then just do something like this:

SELECT pets.ID, pets.Type
FROM pets,petprefs
WHERE pets.Type=petprefs.Type
GROUP BY pets.ID
ORDER BY petprefs.rank

The type with a lower value for rank would always be selected before the type(s) with a higher rank.

Amber
This makes sense. Thanks
Theo
Its a bit of a workaround though. If only there was no need for a another table.
Theo
+1  A: 

I'm fully agree with answer of Rax Olgud. Also can add hint to use ROW_NUMBER function with partition syntax - you get possibility to write more complex condition (then MAX(Type) . Then in WHERE section just filter records by rownum_alias = 1

Update:

select * from (
select ID, Type, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Type DESC) rn
FROM #temp
) a where rn = 1

In contradiction to GROUP BY solution this allows to place any columns in select statement (not only grouping)

Dewfy
Dewfy, could you please elaborate your answer
Theo
@Theo - done, just appended an example
Dewfy
This answer and method is brilliant. It virtually solves any filtering scenario required by a developer. ANY SCENARIO!!!!! You've made my year. My client will be so happy now that I have managed to successfully filter a list of 10000 items with 20 columns. EXCELLENT.
Theo
@Theo You are wellcome
Dewfy