tags:

views:

45

answers:

3

I'm not even sure it's possible to do this but I want to order a query based on the maximum value of one of three columns.

Example table structure: guid, column1, column2, column3

Columns 1-3 have numerical values and I want to order the select statement based on the maximum value of 1, 2 OR 3.

For example:

record column1  column2  column3    
---------------------------------
1      5        0        2
2      2        0        6
3      0        1        2

Would be ordered record 2, 1, 3 because 6 is the maximum value of the three fields across the three records, record 1 is the second and record 3 is the third.

Does this make any sense?

Thanks.

+3  A: 

It may be possible to do in a select query (possibly using something like case when though I'm not sure that's allowed in the order by clause itself, YMMV depending on the DBMS) but it's rarely a good idea to use per-row calculations if you want your database to scale well as tables get bigger ("not have the performance of a one-legged pig in a horse race", as one of our DBAs eloquently puts it).

In situations like this, I set up an additional (indexed) column to hold the maximum and ensure that the data integrity is maintained by using an insert/update trigger to force that new column to the maximum of the other three.

Because most database tables are read far more often than written, this amortises the cost of the calculation across all the reads. The cost is borne only when the data is updated and the queries become blindingly fast since you're ordering on a single, indexed, column:

select f1, f2, f3 from t order by fmax desc;
paxdiablo
This is a good solution. Just found out about GREATEST under MySQL but it's kind of slow. May use this solution if the cost works out better.
Tom
Depends on size of table, and relative frequency of selects and inserts, but if your solution needs to scale, this is sensible. GREATEST is good enough for tables you know aren't going to grow very big.
SamStephens
It's a table of about 4500 records but this table will continually grow. Right now using GREATEST costs about 8 seconds to return the recordset which is unacceptable. I'm going to assume that the cost of updating another field with the max of these three anytime one of the three is updated is less than that.
Tom
+1  A: 

As mentioned here, what you want is an equivalent of the GREATEST function.

In the absence of that, and assuming you've defined a UDF LargerOf to return the largest of two numbers, use

SELECT *
FROM Table
ORDER BY LargerOf(LargerOf(column1, column2), column3)
SamStephens
Thanks, I should have mentioned that I am using MySQL which does have GREATEST. Never heard of it before today!
Tom
Hahaha, I didn't even look properly, for some reason I assume you were using TSQL. My mistake :)
SamStephens
No, I changed it to MySQL. Had it as T-SQL as I thought T-SQL was platform independent and described the language of SQL =)
Tom
+1  A: 
create table myTable
(column1 int, column2 int, column3 int)
go


insert into myTable
values (5, 0 , 2)
go

insert into myTable
values (2, 0 , 6)
go

insert into myTable
values (0, 1 , 2)
go


select *
from mytable
order by case when column1 > column2 and column1 > column3 then column1
when column2 > column3 then column2
else column3 end desc
JBrooks
That totally works, thanks. Going to use GREATEST though, never heard of it before today =)
Tom
Greatest() is not a sql server built in function - it is Oracle. You can easily create your own, but you should still know how to do the sort with a CASE statement.
JBrooks
GREATEST is supported by MySQL and PostgreSQL, including Oracle. SQLite provides similar functionality using MAX: `MAX(col1, col2, col3)`
OMG Ponies