MySQL Proc OrderBy Case Not Allowing More Than One Column - mysql

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

Related

MySQL: How to use CASE for ORDER BY clause

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.

MySQL query assignment Error

When I following query
Select
case
when (#nume=Start_Date) then null
when (#nume!=Start_Date) then #num
End,
case
when (#nume=Start_Date and #nume:=End_Date) then null
when (#nume!=Start_Date) then #nume
End,
case
when (#nume!=Start_Date and #nume:=End_Date and #num:=Start_Date) then #nume
End
from P,(Select #num:=(Select Start_Date from P order by Start_Date desc Limit 1),#nume:=(Select End_Date from P order by Start_Date desc Limit 1 )) as A
;
In the next turn it assigns integer 1 value to #nume, rather than Date as it is supposed to.
"as it is supposed to". Hmmm, the documentation explicitly states:
As a general rule, other than in SET statements, you should never
assign a value to a user variable and read the value within the same
statement. For example, to increment a variable, this is okay:
SET #a = #a + 1;
For other statements, such as SELECT, you might get the results you
expect, but this is not guaranteed. In the following statement, you
might think that MySQL will evaluate #a first and then do an
assignment second:
SELECT #a, #a:=#a+1, ...;
However, the order of evaluation for expressions involving user
variables is undefined.
Your interpretation of what your code is supposed to do is in direct contradiction to the documentation. I would suggest that you ask another question, describing the problem you are trying to solve, and including sample data and desired results.

mysql comparison and encoding

I have a problem with MySQL here, it's quite strange actually... it's a real headbreak, I've been trying a lot of things, sticking some COLLATE, CAST, CONVERT,... but nothing, maybe i'm not doing it the right way, but I'm really lost here.
If some pro has a tip ;) here is my problem:
SELECT col FROM tabl LIMIT 0,1
returns: helloworld01
CASE WHEN((SELECT col FROM tabl LIMIT 0,1) = 'helloworld_01') THEN 'ok' ELSE 'ko' END
returns: ok
CASE WHEN(SUBSTR('helloworld_01',1,1) = 'h') THEN 'ok' ELSE 'ko' END
returns: ok
BUT and this is where it get strange
CASE WHEN(SUBSTR((SELECT col FROM tabl LIMIT 0,1),1,1) = 'h')
THEN 'ok' ELSE 'ko' END
returns: ko
after manually checking each letter i found that the result is quite strange ... numbers and letters in correct order but each character isn't the one supposed to be ... i get something like lsuejwodhb_65
.... but do not change at each request ... and they do not matche their CHAR code either ....
That's because in your below query it's not always guaranteed to output helloworld_01 unless you have only one row which is very rare; since you have not used any order by clause. So the data returned may be different and so your condition is not matching at all. To be sure use a order by clause. Again, without an order by using LIMIT clause makes no sense.
SELECT col FROM tabl order by col LIMIT 0,1
Try your strange query like below and see if it matches this time
CASE WHEN(SUBSTR((SELECT col FROM tabl order by col LIMIT 0,1),1,1) = 'h')
THEN 'ok' ELSE 'ko' END

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.

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