MySql简单的case表达式没有返回正确的数据

时间:2018-03-09 01:41:34

标签: mysql sql

我有一个employee表格如下:

+--------+----------+-----------+------------+----------+-----------------+---------+--------------------+--------------------+
| emp_id | fname    | lname     | start_date | end_date | superior_emp_id | dept_id | title              | assigned_branch_id |
+--------+----------+-----------+------------+----------+-----------------+---------+--------------------+--------------------+
|      1 | Michael  | Smith     | 2005-06-22 | NULL     |            NULL |       3 | President          |                  1 |
|      2 | Susan    | Barker    | 2006-09-12 | NULL     |               1 |       3 | Vice President     |                  1 |
|      3 | Robert   | Tyler     | 2005-02-09 | NULL     |               1 |       3 | Treasurer          |                  1 |
|      4 | Susan    | Hawthorne | 2006-04-24 | NULL     |               3 |       1 | Operations Manager |                  1 |
|      5 | John     | Gooding   | 2007-11-14 | NULL     |               4 |       2 | Loan Manager       |                  1 |
|      6 | Helen    | Fleming   | 2008-03-17 | NULL     |               4 |       1 | Head Teller        |                  1 |
|      7 | Chris    | Tucker    | 2008-09-15 | NULL     |               6 |       1 | Teller             |                  1 |
|      8 | Sarah    | Parker    | 2006-12-02 | NULL     |               6 |       1 | Teller             |                  1 |
|      9 | Jane     | Grossman  | 2006-05-03 | NULL     |               6 |       1 | Teller             |                  1 |
|     10 | Paula    | Roberts   | 2006-07-27 | NULL     |               4 |       1 | Head Teller        |                  2 |
|     11 | Thomas   | Ziegler   | 2004-10-23 | NULL     |              10 |       1 | Teller             |                  2 |
|     12 | Samantha | Jameson   | 2007-01-08 | NULL     |              10 |       1 | Teller             |                  2 |
|     13 | John     | Blake     | 2004-05-11 | NULL     |               4 |       1 | Head Teller        |                  3 |
|     14 | Cindy    | Mason     | 2006-08-09 | NULL     |              13 |       1 | Teller             |                  3 |
|     15 | Frank    | Portman   | 2007-04-01 | NULL     |              13 |       1 | Teller             |                  3 |
|     16 | Theresa  | Markham   | 2005-03-15 | NULL     |               4 |       1 | Head Teller        |                  4 |
|     17 | Beth     | Fowler    | 2006-06-29 | NULL     |              16 |       1 | Teller             |                  4 |
|     18 | Rick     | Tulman    | 2006-12-12 | NULL     |              16 |       1 | Teller             |                  4 |
+--------+----------+-----------+------------+----------+-----------------+---------+--------------------+--------------------+

我正在尝试为出纳员转换数据,如下所示:

SELECT 
    e.emp_id,
    e.fname,
    e.lname,
    CASE e.title
        WHEN 'Head Teller' THEN 'Head Teller'
        WHEN 'Teller' AND YEAR(e.start_date) > 2007 THEN 'Teller Trainee'
        WHEN 'Teller'AND YEAR(e.start_date) < 2006 THEN 'Experienced Teller'
        WHEN 'Teller' THEN 'Teller'
        ELSE 'Non-Teller'
    END `title`
FROM
    employee e

然而像迈克尔史密斯这样的员工出现在Teller Trainee而不是Non-Teller,如下所示:

+--------+----------+-----------+----------------+
| emp_id | fname    | lname     | title          |
+--------+----------+-----------+----------------+
|      1 | Michael  | Smith     | Teller Trainee |
|      2 | Susan    | Barker    | Teller Trainee |
|      3 | Robert   | Tyler     | Teller Trainee |
|      4 | Susan    | Hawthorne | Teller Trainee |
|      5 | John     | Gooding   | Teller Trainee |
|      6 | Helen    | Fleming   | Head Teller    |
|      7 | Chris    | Tucker    | Teller Trainee |
|      8 | Sarah    | Parker    | Teller Trainee |
|      9 | Jane     | Grossman  | Teller Trainee |
|     10 | Paula    | Roberts   | Head Teller    |
|     11 | Thomas   | Ziegler   | Teller Trainee |
|     12 | Samantha | Jameson   | Teller Trainee |
|     13 | John     | Blake     | Head Teller    |
|     14 | Cindy    | Mason     | Teller Trainee |
|     15 | Frank    | Portman   | Teller Trainee |
|     16 | Theresa  | Markham   | Head Teller    |
|     17 | Beth     | Fowler    | Teller Trainee |
|     18 | Rick     | Tulman    | Teller Trainee |
+--------+----------+-----------+----------------+

注意:使用搜索案例表达式时,如下所示:

SELECT 
    e.emp_id,
    e.fname,
    e.lname,
    CASE
        WHEN e.title = 'Head Teller'
            THEN 'Head Teller'
        WHEN e.title = 'Teller'
            AND YEAR(e.start_date) > 2007
            THEN 'Teller Trainee'
        WHEN e.title = 'Teller'
            AND YEAR(e.start_date) < 2006
            THEN 'Experienced Teller'
        WHEN e.title = 'Teller'
            THEN 'Teller'
        ELSE 'Non-Teller'
    END `title`
FROM
    employee e

输出正确如下:

+--------+----------+-----------+--------------------+
| emp_id | fname    | lname     | title              |
+--------+----------+-----------+--------------------+
|      1 | Michael  | Smith     | Non-Teller         |
|      2 | Susan    | Barker    | Non-Teller         |
|      3 | Robert   | Tyler     | Non-Teller         |
|      4 | Susan    | Hawthorne | Non-Teller         |
|      5 | John     | Gooding   | Non-Teller         |
|      6 | Helen    | Fleming   | Head Teller        |
|      7 | Chris    | Tucker    | Teller Trainee     |
|      8 | Sarah    | Parker    | Teller             |
|      9 | Jane     | Grossman  | Teller             |
|     10 | Paula    | Roberts   | Head Teller        |
|     11 | Thomas   | Ziegler   | Experienced Teller |
|     12 | Samantha | Jameson   | Teller             |
|     13 | John     | Blake     | Head Teller        |
|     14 | Cindy    | Mason     | Teller             |
|     15 | Frank    | Portman   | Teller             |
|     16 | Theresa  | Markham   | Head Teller        |
|     17 | Beth     | Fowler    | Teller             |
|     18 | Rick     | Tulman    | Teller             |
+--------+----------+-----------+--------------------+

我对第一个查询无效的原因感到茫然。

2 个答案:

答案 0 :(得分:4)

基于MySQL doc,它应该是

CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE

OR

CASE
    WHEN search_condition THEN statement_list
    [WHEN search_condition THEN statement_list] ...
    [ELSE statement_list]
END CASE

不是两者兼而有之,我的猜测是MySQL没有将其标记为错误,但不会按照您的想法行事。

来自Robert Rocha的评论:

SQL中有两种CASE语法形式。您可以这样写CASE

CASE 
WHEN case_value = (when_expr1) THEN ...
WHEN case_value = (when_expr2) THEN ...

但是,如果您的所有WHEN子句与具有简单相等条件的相同左侧case_value进行比较,那么这似乎是多余的输入。为方便起见,CASE也支持简写:

CASE case_value
WHEN when_expr1 THEN ...
WHEN when_expr2 THEN ...

这很好。但是您使用CASE并不像预期的那样工作的原因是您假设您可以使用AND表达式,但优先顺序不起作用就像你想的那样。

您写道:

CASE e.title
WHEN 'Head Teller' THEN ...
WHEN 'Teller' AND YEAR(e.start_date) > 2007 THEN ...

你认为它会像你做的一样工作:

CASE 
WHEN (e.title = 'Head Teller') THEN ...
WHEN (e.title = 'Teller') AND (YEAR(e.start_date) > 2007) THEN ...

但事实上,当您将e.title放在开头时,它会隐式覆盖优先级,就像您已经完成一样:

CASE 
WHEN e.title = ('Head Teller') THEN ...
WHEN e.title = ('Teller' AND YEAR(e.start_date) > 2007) THEN ...

与布尔表达式比较实际上是一种合法的比较:

A = (B AND C)

表达式B AND C是布尔值,因此它将计算为true或false(实际上是MySQL中的整数值1和0)。

因此,您要将A与1或0进行比较。因为在您的情况下Ae.title,我猜它是一个字符串,那个字符串&# 39; s数值将为0(MySQL中的任何字符串都可以通过其前导数字字符(如果有)计算为数值,如果没有,则为0)。

因此,您的e.title将被视为0,并且它与之比较的表达式将为0,因为'Teller'被视为数值0,用于布尔评估。

由于0 = 0为真,因此CASE中的条件必然为真。

底线:如果您有复杂的条件,则无法使用CASE语法的简写版本。明确写出每个条件。

答案 1 :(得分:0)

来自:http://www.mysqltutorial.org/mysql-case-statement/

  

简单的CASE语句只允许您将表达式的值与一组不同的值进行匹配。为了执行更复杂的匹配(例如范围),可以使用搜索的CASE语句。搜索到的CASE语句等同于IF语句,但是它的构造更具可读性。