MySQL: How to use CASE for ORDER BY clause - mysql

I have a stored procedure that must return a table after filtering rows based on inputs. Two of the inputs are sort_column and sort_dir. The query must ORDER BY sort_column in the sort_dir direction(ASC or DESC).
I have tried the following queries but in vain. The queries below have been simplified to only contain the relevant clauses. The other filters work correctly with no issues.
SELECT * FROM table ORDER BY sort_column sort_dir
SELECT * FROM table ORDER BY CASE sort_column
WHEN 'col1' THEN col1_name
WHEN 'col2' THEN col2_name END
CASE sort_dir WHEN 'asc' THEN ASC
ELSE DESC END
I concatenated the 2 inputs to 1 in the format _ and tried this:
SELECT * FROM table ORDER BY CASE sort_input
WHEN 'col1_asc' THEN col1_name ASC
WHEN 'col1_desc' THEN col1_name DESC
WHEN 'col2_asc' THEN col2_name ASC
WHEN 'col2_desc' THEN col2_name DESC END
I always get error #1064. It is different in each of the above cases but always points to the 'CASE' part. This is the error for option number 2 mentioned above
##1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHEN 'col1' THEN col1_name END CASE 'asc' WHEN 'desc' THEN DESC ELSE ' at line 4
The problem doesn't seem to be the column name. It is the sort direction that isn't working. If I try each of the above options without the 'ASC' and 'DESC' parts, there is no problem.
Am I doing anything wrong here?
Is there a better way to go about this apart from CASE?
MySQL version: 5.6

The best approach is multiple cases:
ORDER BY (CASE WHEN sort_input = 'col1_asc' THEN col1_name END) ASC,
(CASE WHEN sort_input = 'col1_desc' THEN col1_name END) DESC,
(CASE WHEN sort_input = 'col2_asc' THEN col2_name END) ASC,
(CASE WHEN sort_input = 'col2_desc' THEN col2_name END) DESC,
This may seem verbose. But, remember that CASE is an expression that returns a single value. Hence you cannot include ASC and DESC as part of the THEN.
Also important is the issue of data types. The SQL compiler decides on a single type for CASE expression. This can cause unexpected issues when the columns have different types.
The simplest solution is just to use multiple CASE expressions.

Related

MYSQL Creating table as select with xase statement converting field to numbered value

I have the following MYSQL query which creates table as select statement but having a case statment to change field formats to numbered fields to compare:
CREATE TABLE wm.bochg
AS
SELECT
wca.bochg.BochgID,
wca.bochg.SecID,
wca.bochg.OldOutValue,
wca.bochg.NewOutValue,
case when NewOutValue+0.0 >= OldOutValue+0.0 then NewOutValue ELSE '' END AS test2
from wca.bochg
WHERE
wca.bochg.SecID in (select secid from client.pfisin where accid = 416)
AND (wca.bochg.BochgID is null or wca.bochg.BochgID =
(select subbochg.BochgID from wca.bochg as subbochg
where subbochg.secid=bochg.secid
AND subbochg.Actflag <> 'D'
AND subbochg.NewOutValue+0.0 >= subbochg.OldOutValue+0.0
order by subbochg.BochgID desc limit 1)
or wca.bochg.BochgID is NULL);
However I am getting warnings when this is created saying:
'Truncated incorrect DOUBLE value: '' '
This is due to my case statment and the and clause within my subquery. Is there a way to cater for this issue and get rid of the warning message above going forward? Thanks
You are mixing datatypes in the case statement. Use something else than a string '' for the ELSE part (NULL, 0 or anything that suits your purpose).

MySQL Proc OrderBy Case Not Allowing More Than One Column

I have a proc that needs to order the query by different fields depending on a parameter. To accomplish this I have created a simple case statement for my ORDER BY command which works great until I add a second sort field. I'm sure it's just a syntax issue, but I can't seem to find anything on this issue.
ORDER BY
CASE _sort
WHEN 'random' THEN RAND()
WHEN 'latest' THEN u.updated, ut.sort
WHEN 'alpha' THEN u.pageTitle, ut.sort
ELSE ut.sort
END
ASC
LIMIT _limit;
Adding the , ut.sort to each WHEN is what throws the error. When removed the proc works fine.
ORDER BY
CASE _sort WHEN 'random' THEN RAND()
WHEN 'latest' THEN u.updated
WHEN 'alpha' THEN u.pageTitle
ELSE 1
END, ut.sort

Using 'case' in ORDER BY (MySQL)

I'm working in a procedure that returns a huge select where I wan't define how it is order.
I wan't choose one of three fields and if it will be ascending or descending, if none of the three options was define, it returns by default the first field in descending
this way
ORDER BY
CASE option1
WHEN 0 THEN
CASE option2
WHEN 0 THEN firstField DESC
WHEN 1 THEN firstField ASC
END
WHEN 1 THEN
CASE option2
WHEN 0 THEN secondField DESC
WHEN 1 THEN secondField ASC
END
WHEN 2 THEN
CASE option2
WHEN 0 THEN thirdField DESC
WHEN 1 THEN thirdField ASC
END
ELSE
firstField DESC
END
END;
Of course, this didn't work... mysql acuses errors in words 'DESC' and 'ASC', how can I make this works??
In order to do this, you have to move the DESC/ASC to outside the case as they come after the expression.
You should also separate the fields. In a CASE statement if the fields have different datatypes, they will be converted into one that fits all (usually VARCHAR) and this can mess up the ordering.
You could do something like:
ORDER BY CASE WHEN option1=0 AND option2=0 THEN firstField END DESC,
CASE WHEN option1=0 AND option2=1 THEN firstField END ASC,
CASE WHEN option1=1 AND option2=0 THEN secondField END DESC,
CASE WHEN option1=1 AND option2=1 THEN secondField END ASC,
CASE WHEN option1=2 AND option2=0 THEN thirdField END DESC,
CASE WHEN option1=2 AND option2=1 THEN thirdField END ASC,
firstField DESC
Each case will return NULL for all rows when not applicable and thus have the same value. In fact the first case is unnecessary as it will be caught by the default, but I have included it for clarity. This may result in a hugely expensive ordering process however!
I think I'd much rather dynamically build the SQL and I'd use an array of allowed ordering values to keep it secure.

Best way to perform mySQL queries and arrange the results

I need to be able to display the results of the below query in a specific order. For example: showing featured listings before the rest of the results.
WHERE IS `featured-listing` && WHERE IS NOT `featured-listing`
Could probably run 2 queries and a union right, bu is that the most effective solution? I know this can be done with one query I just cant remember how it/s done. Any and all help is appreciated.
SELECT `Assigned-Regions`,`Description`,`Category`,`Start-Date` FROM `adds` WHERE `Status` = "Active" ORDER BY `Start-Date` DESC
I would use a case statement for ORDER BY.
So something like
SELECT ... ORDER BY (CASE WHEN featured-listing THEN 1 ELSE 2) ASC, some-other-field ASC
Sounds like all you need is to add an ORDER BY clause to your query.
If featured-listing column is integer datatype and contains values of 1 or 0 (1=is featured listing, 0=not a featured listing), then you could simply add something as simple as:
ORDER BY `featured-listing` DESC, `Start-Date` DESC
Or, you could use an expression:
ORDER BY IF(`featured-listing`=1,1,0) DESC, `Start-Date` DESC
you can do conditional ordering.. not sure what featured-listing is without seeing some data but this is the logic for conditional ordering
SELECT `Assigned-Regions`,`Description`,`Category`,`Start-Date`
FROM `adds`
WHERE `Status` = "Active"
ORDER BY
CASE WHEN `featured-listing` THEN 1 ELSE 2 END ASC,
`Start-Date` DESC

Add an overall order with case order

I have a sql with a where statement and then an ordering statment.
My ordering statement is like this
'ORDER BY CASE
WHEN '.$col.' LIKE \''.$searchTerm.'\' THEN '.$c_0++.'
WHEN '.$col.' LIKE \''.$searchTerm.'%\' THEN '.$c_20++.'
WHEN '.$col.'LIKE \'%'.$searchTerm.'%\' THEN '.$c_40++.'
ELSE '.$c_60.' END,'.$col;
This gets done a couple of times depending on how many columns and then also splitting my search term up. This works pretty well but when there are couple of results matching the first order statement they display then on ID order, which is not what I want.
How do I add ORDER BY 'RELEASE_DATE' DESC to this.
I have tried adding it my sql in numorous places but just get sql santex errors coming back to me
You add another clause to the order by:
ORDER BY (CASE WHEN '.$col.' LIKE \''.$searchTerm.'\' THEN '.$c_0++.'
WHEN '.$col.' LIKE \''.$searchTerm.'%\' THEN '.$c_20++.'
WHEN '.$col.'LIKE \'%'.$searchTerm.'%\' THEN '.$c_40++;
ELSE '.$c_60.'
END),
(CASE WHEN '.$col.' LIKE \''.$searchTerm.'\' THEN RELEASE_DATE END) desc,
'.$col