Reputation: 121
What would be the most efficient way to sort a query by looking at the largest column value in each row?
For example:
Dan | 5 | 0 | 3
Moe | 0 | 9 | 2
Joe | 3 | 3 | 8
Sorting this dataset should return: Moe, Joe, Dan
My dataset is more complicated than above so I am trying to avoid any combination of subqueries with group by max.
Upvotes: 3
Views: 702
Reputation: 230
I almost never sort on the database. In this case, where the sorting is complicated, and more complex than the model you presented, I typically take the data out of the database and sort it in code.
I have always been rewarded by increased performance when I do this. Its much cheaper to sort 8000000 rows in memory than it is in the database. Since your data model is complex, writing an algorithm to sort this is more flexible than having to write sql - you can write code that is resistant to schema change, and will continue to obey your rules.
Upvotes: 0
Reputation: 176034
You could use CROSS APPLY
:
SELECT *
FROM tab t
CROSS APPLY (SELECT MAX(col) c FROM (VALUES(t.col1),(t.col2),(t.col3)) sub(col)) s
ORDER BY s.c DESC;
Output:
┌──────┬──────┬──────┬──────┬───┐
│ name │ col1 │ col2 │ col3 │ c │
├──────┼──────┼──────┼──────┼───┤
│ Moe │ 0 │ 9 │ 2 │ 9 │
│ Joe │ 3 │ 3 │ 8 │ 8 │
│ Dan │ 5 │ 0 │ 3 │ 5 │
└──────┴──────┴──────┴──────┴───┘
Great answer. I don't suppose there's a way to do this for an arbitrary number of columns (without dsql) is there?
There is a way without dynamic SQL:
SELECT DISTINCT t.*, c.s
FROM tab t
CROSS APPLY (VALUES(CAST((SELECT t.* for XML RAW) AS xml))) B(XMLData)
CROSS APPLY (SELECT MAX(a.value('.','INT') ) s
FROM B.XMLData.nodes('/row') AS C1(n)
CROSS APPLY C1.n.nodes('./@*') AS C2(a)
WHERE a.value('local-name(.)','varchar(100)') LIKE 'col%'
-- filtering based on name
-- it is also possible to JOIN and filter
-- based on metadata like sys.columns
) C
ORDER BY s DESC;
Upvotes: 5