case 语句不返回所有值

Posted

技术标签:

【中文标题】case 语句不返回所有值【英文标题】:case statement not returning all the value 【发布时间】:2021-10-22 19:55:31 【问题描述】:

我有一个 case 语句将多个条件放入一个字段中。

Select 
    *,
    case 
        when day <= 30 then 'Expiration < 30 days'
        when day between 31 and 60 then 'Expiration between 31 and 60 days'
        when day between 61 and 90 then 'Expiration between 61 and 90 days'
        when day > 90 then 'Expiration > 90 days' 
    end Expiration_Version
from 
    tb1;

在指定 case 条件后,我需要在这里计算每个条件的计数,但我遇到的一个问题是,如果特定条件没有返回结果,那么 case when 语句将不包括该条件。即使没有结果,我也希望所有条件都返回。在这种情况下,计数将为 0。

当前状态: 如果有一个条件不满足,比如没有少于 30 天的过期,“过期

Expiration Version                           Count
Expiration between 31 and 60 day              xx
Expiration between 61 and 90 days             xx
Expiration > 90 days                          xx

我喜欢什么:

Expiration Version                           Count
Expiration < 30 days                          0
Expiration between 31 and 60 day              xx
Expiration between 61 and 90 days             xx
Expiration > 90 days                          xx

【问题讨论】:

day = 30 的值会发生什么?? 一个 hacky 方法是将 4 个查询合并在一起。 @Isolated 我想过这个问题。但是 union 共享相同的字段,然后我会在过期版本中丢失其他 3 个类别 应该可以工作.... select 'expires in 30' as exp_group, count(id) from table where day 【参考方案1】:

就像@nir-h 在他的回答中所说的那样,您可以在“过期标签”值和您的桌子之间创建一个LEFT JOIN

我将第一个区间设置为 0 到 30(包括 30)。

最后一个间隔完成列的值必须高于最大天数,才能不排除表格的任何行。

Postgresql(和 SQL Server):

我不知道您使用的是哪个 RDBMS。此查询适用于 Postgresql,但您可以对其进行调整,使其适用于另一个 RDBMS。

fiddle

SELECT e.expiration_lavel AS Expiration_Version , count(tb1.day) AS "Count"

FROM (VALUES
      (1, 0, 30, 'Expiration <= 30 days'),
      (2, 31, 60, 'Expiration between 31 and 60 days'),
      (3, 61, 90, 'Expiration between 61 and 90 days'),
      (4, 91, 1000, 'Expiration > 90 days')) e (id, start, finish, expiration_lavel)
      
LEFT JOIN tb1 ON tb1.day BETWEEN e.start AND e.finish

GROUP BY e.id, e.expiration_lavel

ORDER BY e.id;

Oracle(和 MySql):

SELECT e.lavel Expiration_Version, count(tb1.day) Count

FROM (SELECT 1 id, 0 f, 30 t, 'Expiration <= 30 days' lavel
      FROM dual

      UNION ALL

      SELECT 2, 31, 60, 'Expiration between 31 and 60 days'
      FROM dual

      UNION ALL

      SELECT 3, 61, 90, 'Expiration between 61 and 90 days' 
      FROM dual

      UNION ALL

      SELECT 4, 91, 1000, 'Expiration > 90 days'
      FROM dual) e
      
LEFT JOIN tb1 ON tb1.day BETWEEN e.f AND e.t

GROUP BY e.id, e.lavel

ORDER BY e.id; 

输出我的样本数据:

Expiration_Version Count
Expiration <= 30 days 2
Expiration between 31 and 60 days 1
Expiration between 61 and 90 days 1
Expiration > 90 days 0

【讨论】:

【参考方案2】:

您可以使用四个可能的 Expiration_Version 值创建一个表,然后在该表和计算每个可能值出现次数的表之间执行左连接。这样,对于没有出现的值,您将获得 Null。

【讨论】:

以上是关于case 语句不返回所有值的主要内容,如果未能解决你的问题,请参考以下文章

SQL CASE 语句返回重复值

c语言case

如何使用 case 语句中的函数返回值以选择每个函数的 MAX?

js中switch语句中case值可不可以表示一个范围

MySQL的if,case语句

Shell脚本------条件语句(条件测试,if语句,case语句)