MySQL - 如果在SELECT中使用CASE,则忽略WHERE条件

时间:2017-05-16 08:14:00

标签: mysql database case where

在我的数据库中,有些用户具有永久或有限的访问权限。

status: 1 = active
status: 2 = blocked

如果访问受限,则从有效期到有效期为止。问题是WHERE条件忽略了CASE。

在此示例中,我只想要状态为2(=已阻止)的用户。

SELECT   `id`,
         `username`,
         CASE
           WHEN (`status` = 1 AND `valid` = 'limited' AND (`valid_from` > CURDATE() OR `valid_till` < CURDATE() ) ) THEN 2
           WHEN (`status` = 2 AND `valid` = 'limited' AND (`valid_from` > CURDATE() OR `valid_till` < CURDATE() ) ) THEN 1
           ELSE `status`
         END as `status`,
FROM     `table`
WHERE    `status` = 2
ORDER BY `id` asc

为什么WHERE条件会忽略我的CASE?

修改

这就是我的数据库的样子。

username | status | valid     | valid_from | valid_till
---------------------------------------------------------
Peter    | 1      | unlimited | 2017-05-01 | 2020-05-01 |
Mike     | 2      | unlimited | 2017-05-01 | 2017-05-31 |
Janet    | 1      | limited   | 2017-01-01 | 2017-02-01 |
Ari      | 2      | limited   | 2017-01-01 | 2017-02-01 |
Tina     | 1      | limited   | 2018-05-01 | 2020-05-01 |
Rick     | 2      | limited   | 2018-05-01 | 2020-05-01 |
Donald   | 1      | limited   | 2017-05-01 | 2020-05-01 |
James    | 2      | limited   | 2017-05-01 | 2020-05-01 |

是否可以与CASE正确匹配,或者我还需要编辑我的WHERE条件:

SELECT   `id`,
         `username`,
         CASE
           WHEN (`status` = 1 AND `valid` = 'limited' AND (`valid_from` > CURDATE() OR `valid_till` < CURDATE() ) ) THEN 2
           WHEN (`status` = 2 AND `valid` = 'limited' AND (`valid_from` > CURDATE() OR `valid_till` < CURDATE() ) ) THEN 1
           ELSE `status`
         END as `status`,
FROM     `table`
WHERE  ( `status` = 2 AND `valid` = 'unlimited' ) OR
       ( `status` = 1 AND `valid` = 'limited' AND ( `valid_from` > CURDATE() OR `valid_till` < CURDATE() ) )
ORDER BY `id` asc

1 个答案:

答案 0 :(得分:0)

您的表格中有一列status。因此,WHERE status = 2会解除状态为1的所有记录。但是,当valid = 'limited'和日期范围不适用于今天时,您似乎想要更正状态。因此,您希望将WHERE子句应用于此更正的状态。您可以先获取更正后的状态,然后在此处写一个查询来执行此操作:

SELECT *
FROM
(
  SELECT 
    id,
    username,
    CASE
      WHEN (status = 1 AND valid = 'limited' AND (valid_from > CURDATE() OR valid_till < CURDATE() ) ) THEN 2
      WHEN (status = 2 AND valid = 'limited' AND (valid_from > CURDATE() OR valid_till < CURDATE() ) ) THEN 1
      ELSE status
    END as status_today
  FROM table
) corrected
WHERE status_today = 2
ORDER BY id asc;