I tried to write my own window function in mysql but found something I don't understand as shown below.
The table employee has 13 rows,
+----+------+--------+
| id | name | salary |
+----+------+--------+
| 1 | a | 123 |
| 2 | a | 234 |
| 4 | a | 254 |
| 8 | a | 724 |
| 9 | a | 432 |
| 12 | a | 123 |
| 3 | b | 124 |
| 10 | b | 333 |
| 11 | b | 11 |
| 13 | b | 628 |
| 5 | c | 111 |
| 6 | c | 777 |
| 7 | c | 666 |
+----+------+--------+
So if I use the following query,
select name, salary,
(case name when @prev_name then @rank := @rank + 1
else @prev_name := name and @rank := 1 end) + 1 as Rank
from employee , (select @rank := 0, @prev_name := null ) r
order by name ;
The results are
+------+--------+------+
| name | salary | Rank |
+------+--------+------+
| a | 123 | 1 |
| a | 234 | 2 |
| a | 254 | 3 |
| a | 724 | 4 |
| a | 432 | 5 |
| a | 123 | 6 |
| b | 124 | 7 |
| b | 333 | 8 |
| b | 11 | 9 |
| b | 628 | 10 |
| c | 111 | 11 |
| c | 777 | 12 |
| c | 666 | 13 |
+------+--------+------+
with 14 warnings,
+---------+------+--------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'c ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'c ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'c ' |
+---------+------+--------------------------------------------------------------------+
But if I change the order inside the else
clause,
select name, salary,
(case name when @prev_name then @rank := @rank + 1
else @rank := 1 and @prev_name := name end) + 1 as Rank
from employee , (select @rank := 0, @prev_name := null ) r
order by name ;
The output is different,
+------+--------+------+
| name | salary | Rank |
+------+--------+------+
| a | 123 | 1 |
| a | 234 | 2 |
| a | 254 | 3 |
| a | 724 | 4 |
| a | 432 | 5 |
| a | 123 | 6 |
| b | 124 | 1 |
| b | 333 | 2 |
| b | 11 | 3 |
| b | 628 | 4 |
| c | 111 | 1 |
| c | 777 | 2 |
| c | 666 | 3 |
+------+--------+------+
without warnings.
My guess is that is related to logical operator short-cut and the return value of the assignment operator. But I could not found any useful information online.
This becomes even more interesting after I tried different ways.
So the following query gives totally different results sometimes,
set @prev_name := null; set @rank := 0;
select name, salary,
(case name when @prev_name then @rank := @rank + 1 else @prev_name := name and @rank := 1 end) + 1 as Rank
from employee order by name ;
+------+--------+------+
| name | salary | Rank |
+------+--------+------+
| a | 123 | 1 |
| a | 234 | 1 |
| a | 254 | 1 |
| a | 724 | 1 |
| a | 432 | 1 |
| a | 123 | 1 |
| b | 124 | 1 |
| b | 333 | 1 |
| b | 11 | 1 |
| b | 628 | 1 |
| c | 111 | 1 |
| c | 777 | 1 |
| c | 666 | 1 |
+------+--------+------+
With 13 warnings,
+---------+------+--------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'c ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'c ' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'c ' |
+---------+------+--------------------------------------------------------------------+