CASE 语句将 NUMBER 转换为 CHAR,但在 Oracle SQL 中保留原始 NUMBER 的 ELSE

Posted

技术标签:

【中文标题】CASE 语句将 NUMBER 转换为 CHAR,但在 Oracle SQL 中保留原始 NUMBER 的 ELSE【英文标题】:CASE statement turning a NUMBER into a CHAR, but the ELSE to keep original NUMBER in Oracle SQL 【发布时间】:2015-01-02 01:08:59 【问题描述】:

我正在尝试创建一个简单的查询,它将当前包含值 0、1、2、3、4、5 的评分/评估列转换为 Terrible、Poor、Bad、Mediocre 和 Good。但正如您所见,标签值只有 5 个,而数字值只有 6 个。

所以数字 5 需要显示为 5,而所有其他数字将变成它们各自的标签(可怕、差等)。

我目前的查询如下:

SELECT  course_id,
		student_id,
		CASE eval
		WHEN 0 THEN 'Terrible'
		WHEN 1 THEN 'Bad'
		WHEN 2 THEN 'Mediocre'
		WHEN 3 THEN 'Fair'
		WHEN 4 THEN 'Good'
		END
		FROM booking;

在以下查询结果中,我知道标记为10121COURSE_ID 的评估值为5 所有其他的都是空的,所以它们是空白的很好。但是10121 需要显示为5

如果我尝试应用ELSE 语句来返回原始值(通过执行inner select 语句),它会显示ERROR at line 9: ORA-00932: inconsistent datatypes: expected CHAR got NUMBER

 COURSE_ID STUDENT_ID CASEEVAL
---------- ---------- --------
     10111   10235000 Good
     10111   10285858 Fair
     10112   10288497
     10112   10092464 Fair
     10113   10235000
     10114   10128018 Terrible
     10114   10288497
     10115   10092464 Terrible
     10115   10128018 Bad
     10116   10128018
     10118   10288497 Bad
     10118   10836444 Fair
     10119   10285858
     10120   10412445 Mediocre
     10121   10836444
     10122   10285858 Good
     10123   10412445 Mediocre
     10125   10095146

【问题讨论】:

Oracle != mysql,我修复了你的标签。 这是case EXPRESSION,不是case语句... 【参考方案1】:

您需要一个ELSE 选项来处理不匹配的情况。使用TO_CHAR 将所有值获取到相同的数据类型。

SELECT  event_id,
        trainee_id,
        CASE eval
            WHEN 0 THEN 'Terrible'
            WHEN 1 THEN 'Bad'
            WHEN 2 THEN 'Mediocre'
            WHEN 3 THEN 'Fair'
            WHEN 4 THEN 'Good'
            ELSE TO_CHAR(eval)
        END
FROM booking;

【讨论】:

这仍然给我“不一致的数据类型:预期的 CHAR 得到 NUMBER”错误。 TO_CHAR() 应该返回 VARCHAR2,而不是 NUMBER。我不明白它是如何导致该错误的。【参考方案2】:

只需使用'5':

SELECT  event_id,
        trainee_id,
        (CASE eval
            WHEN 0 THEN 'Terrible'
            WHEN 1 THEN 'Bad'
            WHEN 2 THEN 'Mediocre'
            WHEN 3 THEN 'Fair'
            WHEN 4 THEN 'Good'
            WHEN 5 THEN '5'
         END
        )
FROM booking;

或者,您可以使用显式 cast() 和默认值 else

SELECT  event_id,
        trainee_id,
        (CASE eval
            WHEN 0 THEN 'Terrible'
            WHEN 1 THEN 'Bad'
            WHEN 2 THEN 'Mediocre'
            WHEN 3 THEN 'Fair'
            WHEN 4 THEN 'Good'
            ELSE cast(eval as varchar2(255))
         END
        )
FROM booking;

我鼓励您使用显式转换。在执行隐式转换时,SQL 可能容易出现难以调试的错误。

【讨论】:

这会起作用,除非我需要这样做,因为可能会出现更多使用 0-4 以外的数字的情况。所以也许如果有 6、7、8、9 等。我不想在查询中写出每一个数字。 @Tootally 。 . .然后使用第二个查询。 @GordonLinoff,我相信在 Oracle SQL CASE 语句中使用 ELSE 而不是 DEFAULT @DavidFaber 。 . .那是因为这是标准,也是所有其他数据库所做的。我不知道自己在想什么,或者至少不知道为什么我的手指在打字。【参考方案3】:

如果您不介意您的查询是特定于 Oracle 的,您也可以使用 DECODE() 函数:

SELECT course_id, student_id
     , DECODE( eval, 0, 'Terrible', 1, 'Bad', 2, 'Mediocre', 3, 'Fair', 4, 'Good', TO_CHAR(eval) )
  FROM booking;

在此实例中比 CASE 节省了一些输入,并且格式化也更容易一些。

第三种选择是将评估分数及其描述存储在单独的表中,然后连接(使用外连接)以获取描述:

SELECT b.course_id, b.student_id, COALESCE(es.eval_desc, TO_CHAR(b.eval))
  FROM booking b, eval_scores es
 WHERE b.eval = es.eval(+)

【讨论】:

以上是关于CASE 语句将 NUMBER 转换为 CHAR,但在 Oracle SQL 中保留原始 NUMBER 的 ELSE的主要内容,如果未能解决你的问题,请参考以下文章

在CASE表达式Oracle SQL中将字符串转换为日期

将嵌套解码转换为等效的 CASE 语句(需要从 Oracle 转换为 PostgreSQL)

将 SQL CASE WHEN 语句转换为 C#

无法将类型为“System.Decimal”的对象强制转换为类型“System.Char[]”。

Oracle date、char、number处理转换(转)

C# 将带有 Case 语句的 SQL 查询转换为 LINQ