MYSQL ORDER BY CASE WHEN not working properly - mysql

MB_KOM are first locations returned from this query, then MLL,MDL...etc.
SELECT *, SUBSTRING(location, 7, 20) AS ExtractString FROM inventory
ORDER BY CASE
WHEN location LIKE "MB_BN%" THEN location END ASC,
CASE
WHEN location LIKE "MB_B%" THEN location END ASC,
CASE
WHEN location LIKE "MB_KOM%" THEN ExtractString+0 END DESC
So what am i missing here?
Edit:
Goal is to get locations in this order:
MB_BN% ASC,
MB_B% ASC,
MB_KOM% DESC,
THEN anything else...
After MB_BN and MB_B and MB_KOM are always some numbers.
Example: MB_KOM199, MB_BN010406, MB_B12

You are using ORDER BY with three expressions, so it sorts by the first expression alone, unless that results in a tie. Then it resolves the tie by the second expression. And so on.
Did you mean to use a single CASE expression with multiple cases?
ORDER BY CASE
WHEN location LIKE 'MB_BN%' THEN location
WHEN location LIKE 'MB_B%' THEN location
WHEN location LIKE 'MB_KOM%' THEN ExtractString+0 END
But that has a few problems:
You can't mix ASC and DESC sort order in the same ORDER BY argument.
You can't mix sorting alphabetically and numerically in the same ORDER BY argument. Even though you used the +0 trick to cast the ExtractString to an numeric, it will be cast back to string to be compatible with the expression.
The CASE has no ELSE, so if the location matches none of the patterns, the result of the expression is NULL, and the sorting will be in some arbitrary order.
Here's a different solution:
SELECT *,
CASE WHEN location LIKE 'MB_BN%' THEN 1
WHEN location LIKE 'MB_B%' THEN 2
WHEN location LIKE 'MB_KOM%' THEN 3
ELSE 4 END AS location_type,
REGEXP_SUBSTR(location, '[[:digit:]]+') AS digits
FROM inventory
ORDER BY location_type ASC,
(CASE location_type WHEN 3 THEN -digits ELSE digits END)+0 ASC;
Dbfiddle

Related

MySQL ORDER BY CASE + operator

I am trying to do a search that would be sorted by relevance.
Let's say the search term contains 3 words: A, B and C. What I am trying to do is to check if the search term is present in the SELECT result and if yes that would increase its rank.
ORDER BY CASE
(
WHEN search_word_A_is_present THEN +1
WHEN search_word_B_is_present THEN +1
WHEN search_word_C_is_present THEN +1
ELSE 0
END
)
DESC
While there is no syntax error and the search runs and sorts by something (that seems different from what I want) but I am not sure what is being added up if anything. How would I go about seeing what the final rank (sum) is at the end for each result? Is this the correct way to do it?
Since in MySQL boolean conditions result in 1 and 0, you can simply add those up
ORDER BY search_word_A_is_present + search_word_B_is_present + search_word_C_is_present
DESC
A more practical example:
ORDER BY col1 = 1 + col2 = 'A' + col3 = 44 DESC

Grouping mysql by a regex?

I am trying to find the count of how many times a location is used in my table of search results, but I want to group together cases where the same post code area start is used. The following groups purely on the text used:
SELECT count(*),
search_browse_log.postcode_start
FROM search_browse_log
GROUP BY postcode_start
ORDER BY count(*) DESC
But in the data, I have for example CR0, CR1, CR2 (postcode starts). I want to group them all together so I have a count of 3 for "CR", rather than 1 each of CR0, CR1 and CR2.
Thanks in advance if you can help!
Use a conditional in the GROUP BY clause to get either 1 or 2 characters, depending on whether the postcode starts with 1 or 2 letters.
GROUP BY IF(postcode_start REGEXP '^[A-Z][A-Z]',
LEFT(postcode_start, 2),
LEFT(postcode_start, 1))
If it's only the first 2 characters of the postcode, you could use the LEFT function in the group by:
SELECT count(*),
LEFT(postcode_start,2) as `postcode_start`
FROM search_browse_log
GROUP BY LEFT(postcode_start,2)
ORDER BY count() DESC
To group by the non-numeric characters at the start of the string:
SELECT count(*),
IF(postcode_start REGEX '^[a-ZA-Z][0-9]',LEFT(postcode_start,1),LEFT(postcode_start,2)) as `postcode_start`
FROM search_browse_log
GROUP BY IF(postcode_start REGEX '^[a-ZA-Z][0-9]',LEFT(postcode_start,1),LEFT(postcode_start,2))
ORDER BY count() DESC
For reference, see https://dev.mysql.com/doc/refman/5.7/en/regexp.html#operator_regexp

Order by date and field

I have SELECT query with LEFT JOINT (SELECT) and order by COALESCE(SELECT2.date, SELECT1.date) but i need to order it too with important field.
So: if row have important = 1 it need to be first, then important = 0 but ordered by coleasce date so as so. Is this even posible?
You could place the important column first in the order by list. Sorting desc (for descending) will place 1 before 0:
order by
important DESC
, coalesce(select2.date, select1.date)
You can even use case to sort the important column in a custom way:
order by
case
when important = 'SENATOR' then 1
when important = 'PATRICIAN' then 2
when important = 'PLEBS' then 3
else 4
end
, coalesce(select2.date, select1.date)

mysql select in aescending or descending order

my id or primary key is and the data type of is VARCHAR(50)
0.0.01
0.0.100
0.0.101
0.0.1011
0.0.201
0.0.501
0.0.99
0.0.999
0.01.0
0.01.10
0.02.10
0.02.20
0.02.99
01.0.0
01.0.99
01.02.99
01.03.444
01.05.88
10.02.99
100.100.100
25.45.1001
99.99.99
I have to get it in sorted order
so i tried this
select id from table order by cast(id as decimal) desc;
but it does not work
the expected order is after running the query
0.0.01
0.0.99
0.0.100
0.0.101
0.0.201
0.0.501
0.0.999
0.0.1011
0.01.0
0.01.10
0.02.10
0.02.20
0.02.99
01.0.0
01.0.99
01.02.99
01.03.444
01.05.88
10.02.99
25.45.1001
99.99.99
100.100.100
i am using mysql for this
Not an easier one but you can use substring_index for each decimal places
select *
from t
order by
substring_index(id,'.',1) * 1,
substring_index(substring_index(id,'.',-2),'.',1) * 1,
substring_index(id,'.',-1) * 1
Explanation
I have use substring_index what it does it will return the piece of string in provided column like in above case i have use id column by the occurrence of delimiter i.e(.) for example a string like 0.1.2 for above 3 sunstring_index usage will return as below
substring_index('0.1.2','.',1) will give result as 0
substring_index(substring_index('0.1.2','.',-2),'.',1) will give result as 1
substring_index('0.1.2','.',-1) will give result as 2
For type casting to number i have multiplied the result of substring_index to 1 so the order by expression will first order the results by the number before first dot then with number before second dot and last the number after second dot in ascending manner
Demo
Sources:
http://www.w3resource.com/mysql/string-functions/mysql-substring_index-function.php
Your ID column has invalid decimal value so casting could not work here.
Try without casting this should work:
select id from table order by id desc;
DEMO

order by case in sql 2005 server

One of the column in my table like this:
Symbol
586fast
urgent
243late
296fast
122late
155fast
I need urgent in first then records with fast order asc then records with late order asc like this:
urgent
586fast
296fast
155fast
243late
122late
I am getting urgent in first row,records with fast and late but they are not in asc order
ORDER BY CASE
when Symbol like '%FUT' then 1
when Symbol like '%CE' then 2
when Symbol like '%PE' then 3
else 4 end
After ordering using case statement provide further ordering by Symbol column itself
ORDER BY CASE
when Symbol like '%FUT' then 1
when Symbol like '%CE' then 2
when Symbol like '%PE' then 3
else 4 end, Symbol asc