Can you add an if statement in ORDER BY?
Well, you can use the IF
function in MySQL (Note the emphasis on function
since there's also an unrelated IF
statement)...:
ORDER BY IF(TYPE='Member', LNAME, GROUPNAME) ASC
However, in this case it seems the better choice (From a flexibility standpoint) would be the CASE
statement:
ORDER BY
CASE `type`
WHEN 'Member' THEN LNAME
WHEN 'Group' THEN GROUPNAME
ELSE 1 END
ASC
Note that the entire block from CASE
to END
is to be considered as a single "unit". The result of which is what you're trying to sort against (Hence why the ASC
comes after the block, rather than inside of it)...
IF statement in ORDER BY Clause of a SELECT Statement in a SQL Server Stored Procedure
ORDER BY
CASE WHEN @switch = 0 THEN Field1 END,
CASE WHEN @Switch = 1 THEN Field2 END
T-SQL IF statements in ORDER BY clauses
There's a gotcha here... you can't mix data types in your case statement, so you need to create different groups of case statements for the different data types.
SELECT
*
FROM
table
ORDER BY
CASE WHEN @SortType = id THEN table.Id END ASC,
CASE WHEN @SortType != id THEN table.Date END ASC
Related blog post:
http://dirk.net/2006/11/14/dynamic-order-by-with-case-statement-in-sql-server-data-type-issues/
Order of execution for an if with multiple conditionals
This type of evaluation is called short-circuiting.
Once the result is 100% clear, it does not continue evaluating.
This is actually a common programming technique.
For example, in C++ you will often see something like:
if (pX!=null && pX->predicate()) { bla bla bla }
If you changed the order of the conditions, you could be invoking a method on a null pointer and crashing. A similar example in C would use the field of a struct when you have a pointer to that struct.
You could do something similar with or:
if(px==null || pX->isEmpty()} { bla bla bla }
This is also one of the reasons that it is generally a good idea to avoid side effects in an if condition.
For example suppose you have:
if(x==4 && (++y>7) && z==9)
If x
is 4
, then y
will be incremented regardless of the value of z
or y
, but if x
is not 4
, it will not be incremented at all.
Use IF statement on ORDER BY
Use multiple clauses in the order by:
ORDER BY type, -- put numbers first
(case when type = 1 then value + 0 end) desc, -- convert values to numbers
value
The problem with using one expression, such as if()
or case
, is that the result is converted to one type. So, you are sorting either numbers or strings, but not both at the same time.
How use ASC/DESC inside a ORDER BY if statement?
How about ordering by IF(type=2, -ranking, ranking)
after ordering by type? Negating the ranking will cause the opposite order for that type.
EDIT
Since ranking
is a VARCHAR
column, you would need to to convert it to a number to use this technique.
SELECT * FROM test ORDER BY type ASC, CAST(ranking as SIGNED)*IF(type = 1, 1, -1) ASC;
You can test the code directly at sqlfiddle
Order of execution in IF statement when multiple conditions present
The result will be the same, because &&
is a short-circuiting operator. This means that if the first operand evaluates to false, the second operand will not be evaluated.
What is the effect of ordering if...else if statements by probability?
As a general rule, most if not all Intel CPUs assume forward branches are not taken the first time they see them. See Godbolt's work.
After that, the branch goes into a branch prediction cache, and past behavior is used to inform future branch prediction.
So in a tight loop, the effect of misordering is going to be relatively small. The branch predictor is going to learn which set of branches is most likely, and if you have non-trivial amount of work in the loop the small differences won't add up much.
In general code, most compilers by default (lacking another reason) will order the produced machine code roughly the way you ordered it in your code. Thus if statements are forward branches when they fail.
So you should order your branches in the order of decreasing likelihood to get the best branch prediction from a "first encounter".
A microbenchmark that loops tightly many times over a set of conditions and does trivial work is going to dominated by tiny effects of instruction count and the like, and little in the way of relative branch prediction issues. So in this case you must profile, as rules of thumb won't be reliable.
On top of that, vectorization and many other optimizations apply to tiny tight loops.
So in general code, put most likely code within the if
block, and that will result in the fewest un-cached branch prediction misses. In tight loops, follow the general rule to start, and if you need to know more you have little choice but to profile.
Naturally this all goes out the window if some tests are far cheaper than others.
Related Topics
Composer Installing: the JSON Extension Is Missing
Run Shell Command and Send Output to File
PHP Session Side-Effect Warning with Global Variables as a Source of Data
Using MySQLi from Another Class in PHP
How to Use "Dependency Injection" in Simple PHP Functions, and Should I Bother
Geo-Search (Distance) in PHP/MySQL (Performance)
Destroy or Unset Session When User Close the Browser Without Clicking on Logout
Send PHP Date to JavaScript Date Format
How to Schedule the Execution of a PHP Script on the Server Side
Get Last Insert Id After a Prepared Insert with Pdo
Could Not Instantiate Mail Function. Why This Error Occurring
Phpmyadmin - Count(): Parameter Must Be an Array or an Object That Implements Countable
PHP Array_Filter with Arguments