Home > Software design >  Is it possible to prioritize every column in SQL ORDER BY or is it limited to the order you place th
Is it possible to prioritize every column in SQL ORDER BY or is it limited to the order you place th

Time:07-21

I'm trying to do a very specific ordering with a SQL server. I have tried two different queries, and they're close, but they create an issue that I can't completely fix.

It'll be easier if I show the results I want:

ID Ring_Size W_Size Purity F_Size
D46320 16 3.4 38 94
F15555 10 10.1 4 81
B45555 10 14.01 4 83.1
E64444 10 14.0 2 84.2
E64444 10 14.81 2 84.2
B45445 10 15.1 2 87.1
B45475 10 15.1 4 87.1
E66744 10 15.1 4 87.1

This focuses on ring size in descending order. Then it pairs w_size together in ascending order while also keeping ID's together. Then, finally, when there are matches, it would order the matches by purity ascending.

I can only achieve all but one of these conditions. I keep trading something off.

I can achieve everything except the final ordering by ascending purity with this code:

SELECT 
    ID, Ring_Size, 
    RIGHT(Gspec, CHARINDEX(' ', REVERSE(Gspec)) - 1) AS W_SIZE,
    LEFT(Gspec, CHARINDEX(' ', Gspec) - 1) AS Purity, F_Size 
FROM 
    JewelColl
ORDER BY 
    Ring_Size DESC, 
    RIGHT(Gspec, CHARINDEX(' ', REVERSE(Gspec)) - 1)   ID,
    CAST(LEFT(Gspec, CHARINDEX(' ', Gspec) - 1) AS INT) 

Which will result in:

ID Ring_Size W_Size Purity F_Size
D46320 16 3.4 38 94
F15555 10 10.1 4 81
B45555 10 14.01 4 83.1
E64444 10 14.0 2 84.2
E64444 10 14.81 2 84.2
B45445 10 15.1 4 87.1
B45475 10 15.1 4 87.1
E66744 10 15.1 2 87.1

You'll notice the last three rows for purity had the order changed to 4, 4, 2. Which is purity desc.

I can fix that with another query, but it no longer keeps ID's together:

SELECT 
    ID, Ring_Size, 
    RIGHT(Gspec, CHARINDEX(' ', REVERSE(Gspec)) - 1) AS W_SIZE,
    LEFT(Gspec, CHARINDEX(' ', Gspec) - 1) AS Purity, F_Size 
FROM 
    JewelColl
ORDER BY 
    Ring_Size DESC, 
    RIGHT(Gspec, CHARINDEX(' ', REVERSE(Gspec)) - 1),
    CAST(LEFT(Gspec, CHARINDEX(' ', Gspec) - 1) AS INT), ID 

ID placement is the difference.

Here are the results:

ID Ring_Size W_Size Purity F_Size
D46320 16 3.4 38 94
F15555 10 10.1 4 81
E64444 10 14.0 2 84.2
B45555 10 14.01 4 83.1
E64444 10 14.81 2 84.2
E66744 10 15.1 2 87.1
B45445 10 15.1 4 87.1
B45475 10 15.1 4 87.1

This solves the purity ascending order but it splits up ID's as noted by the order of:

E64444,B45555,E64444

Is there a way to keep the purity ascending order, ID's together, all while still matching W_Size?

Thank you.

CodePudding user response:

You have contradicting requirements in w_size in ascending order while also keeping ID's together, because the same ID may have both a smaller and a larger w_size than another ID. We can get around it by assigning a 'group' W_SIZE. I used MAX_W_SIZE here:

with MyTbl as (
select ID,  Ring_Size, W_Size,  Purity, F_Size, Max_W_Size=max(W_Size) over (partition by ID)
from (values 
 ('D46320', 16, 3.4     ,38 ,94   )
,('E64444', 10, 14.81   ,2  ,84.2 )
,('F15555', 10, 10.1    ,4  ,81   )
,('E64444', 10, 14.0    ,2  ,84.2 )
,('B45445', 10, 15.1    ,2  ,87.1 )
,('B45475', 10, 15.1    ,4  ,87.1 )
,('B45555', 10, 14.01   ,4  ,83.1 )
,('E66744', 10, 15.1    ,4  ,87.1 )
) T(ID, Ring_Size, W_Size,  Purity, F_Size)
)
select * from MyTbl 
order by 
  ring_size desc
, Max_W_Size
, ID
, W_Size
, Purity

I used your results as data; you can replace the VALUES part with your query.

  • Related