当输入值为NULL时,多个CASE语句不起作用

时间:2018-05-23 20:29:21

标签: mysql sql

我有这个SQL查询:

SET @start_date = 'a timestamp at x in time';
SET @end_date = 'a timestamp at x + y in time';

SELECT DISTINCT u.user_id
FROM user_plan u
  JOIN user_feature uf ON uf.user_plan_id = u.id
WHERE uf.status IN ('PENDING_ACTIVE', 'PENDING_INACTIVE')
  AND (
    CASE
      WHEN @start_date IS NULL AND @end_date IS NULL THEN true
      WHEN @end_date IS NOT NULL AND @end_date >= u.created_at AND @start_date IS NULL THEN true
      WHEN @start_date IS NOT NULL AND @start_date <= u.created_at AND @end_date IS NULL THEN true
      WHEN @start_date IS NOT NULL AND @end_date IS NOT NULL AND u.created_at BETWEEN @start_date AND @end_date THEN true
      ELSE false
    END
  ) = true;

start_dateend_date作为输入参数出现。问题是它们可以为空,到目前为止,第三和第四WHEN语句不起作用。

有没有办法简化这个小小的疯狂?这是我可以用我的片段SQL技能走多远。

2 个答案:

答案 0 :(得分:1)

您可以尝试此查询。

在您的情况下,您可以使用OR代替CASE WHEN表达式

SELECT DISTINCT u.user_id
FROM user_plan u
  JOIN user_feature uf ON uf.user_plan_id = u.id
WHERE uf.status IN ('PENDING_ACTIVE', 'PENDING_INACTIVE')
  AND (
    (@start_date IS NULL AND @end_date IS NULL)
    OR
    (
        @end_date IS NOT NULL AND @end_date >= u.created_at
    )
    OR
    (   
        @start_date IS NOT NULL AND @start_date <= u.created_at
    )
    OR
    (   
        @start_date IS NOT NULL AND @end_date IS NOT NULL AND u.created_at BETWEEN @start_date AND @end_date
    )
  )

答案 1 :(得分:1)

假设user_id中的user_plan是唯一的,我会选择:

SELECT u.user_id
FROM user_plan u
WHERE EXISTS (SELECT 1
              FROM user_feature uf 
              WHERE uf.user_plan_id = u.id AND
                    uf.status IN ('PENDING_ACTIVE', 'PENDING_INACTIVE')
             ) AND
      (@end_date IS NULL OR @end_date >= u.created_at) AND
      (@start_date IS NULL OR @start_date <= u.created_at);

即使user_plan.user_id不为空,您仍然可以将此公式与select distinct一起使用,但删除distinct应该是显着的性能提升。