I want to write a query which will sort the results based on multiple conditions.
Please refer to following dummy table
name | domain |
---|---|
Apple | gmail |
.Apple2 | yahoo |
_Apple3 | xyz |
Apple4 | zyx |
Ball | abc |
.Ball2 | efg |
_Ball3 | gmail |
Ball4 | yahoo |
Bear | xyz |
Cat | abc |
I want to sort above table
1 - By Known domain yahoo
followed by gmail
then rest.
So I want to divide result rows in three parts.
1st section with rows having yahoo
as domain then in 2nd section rows with gmail
domain at last rest of the rows.
2 - Alphabetically and all special characters at the end.
Every section should be further sorted alphabetically on name
field with special characters at the end.
Result should look like following table.
name | domain |
---|---|
Ball4 | yahoo |
.Apple2 | yahoo |
Apple | gmail |
_Ball3 | gmail |
Apple4 | zyx |
Ball | abc |
Bear | xyz |
Cat | abc |
_Apple3 | xyz |
.Ball2 | efg |
I have managed to sort result alphabetically with special symbols at bottom with following query but I am not able to get the 1st part of sorting correct i.e sort by known domain.
SELECT * FROM table1
ORDER BY
CASE WHEN name GLOB '[A-Za-z]*'
THEN name
ELSE '~' || name
END COLLATE NOCASE
CodePudding user response:
Use boolean expressions in the ORDER BY
clause:
SELECT * FROM table1
ORDER BY domain = 'yahoo' DESC,
domain = 'gmail' DESC,
name GLOB '[A-Za-z]*' DESC,
LTRIM(LTRIM(name, '.'), '_');
Each of these boolean expressions evaluates to 1
for true
or 0
for false
.
See the demo.
CodePudding user response:
Part 1 - To sort by specific values first you can do something like this
SELECT * FROM table1
ORDER BY CASE
WHEN domain = 'yahoo' then 0
WHEN domain = 'gmail' then 1
ELSE 2
END ASC
Part 2 - Then within that you want to sort by name, so add your existing name sorting to our ORDER BY so we have this:
SELECT * FROM table1
ORDER BY CASE
WHEN domain = 'yahoo' then 0
WHEN domain = 'gmail' then 1
ELSE 2
END ASC,
CASE WHEN name GLOB '[A-Za-z]*'
THEN name
ELSE '~' || name
END COLLATE NOCASE
CodePudding user response:
May not the most performant solution, but it should work with a union in such special cases:
(
SELECT
*
FROM
table1
WHERE
domain like 'yahoo'
ORDER BY
name desc
)
UNION
(
SELECT
*
FROM
table1
WHERE
domain like 'gmail'
ORDER BY
name desc
)
UNION
(
SELECT
*
FROM
table1
WHERE
domain not like 'yahoo'
OR domain not like 'gmail'
ORDER BY
domain desc,
name desc
)