【问题标题】:Working in MY SQL but not in MS SQL Server or ORACLE在 MY SQL 中工作,但不在 MS SQL Server 或 ORACLE 中工作
【发布时间】:2020-05-13 11:17:26
【问题描述】:

在 HackerRANk 这个“https://www.hackerrank.com/challenges/the-report/problem”是问题。 我写了这段代码。

SELECT (CASE 
       WHEN (STUDENTS.MARKS>=70) THEN (STUDENTS.NAME)
       ELSE "NULL"
       END) , GRADES.GRADE , STUDENTS.MARKS FROM STUDENTS
INNER JOIN GRADES ON
                    STUDENTS.MARKS BETWEEN MIN_MARK AND MAX_MARK
ORDER BY GRADES.GRADE DESC, (CASE
         WHEN (STUDENTS.MARKS>=70) THEN  STUDENTS.NAME
         ELSE  STUDENTS.MARKS
         END) ;

我使用的是 MS SQL,但这显示错误:- 消息 245,级别 16,状态 1,服务器 WIN-ILO9GLLB9J0,第 2 行 将 varchar 值“Priya”转换为数据类型 int 时转换失败。

但相同的代码适用于我的 SQL。请帮忙。 任何人都可以建议学习广泛使用的最佳 SQL,以及从哪里学习。

【问题讨论】:

  • 与您的问题无关,但是:字符串常量应该用单引号引起来。双引号用于标识符。所以你应该使用'NULL'

标签: sql sql-server sql-server-2008


【解决方案1】:

假设Name 是一个字符串,marks 是一个数字,那么这段代码在任何数据库中都不起作用:

(CASE WHEN STUDENTS.MARKS >= 70 THEN STUDENTS.NAME
      ELSE STUDENTS.MARKS
 END) ;

然而,MySQL 会进行一种隐式转换,它有时会将字符串转换为数字而不会产生错误。所以在这种情况下它可能不会返回错误,而是将'Pat' 之类的名称转换为0。 (在这种情况下,我不能 100% 确定;我会避免混合这样的类型。)

原因是CASE 表达式返回单一类型。在 SQL 中,当在数字和字符串之间进行选择时,数字胜出。所以,你会得到一个类型转换错误。

不清楚你的意图,但我可能猜到:

ORDER BY GRADES.GRADE DESC,
         (CASE WHEN STUDENTS.MARKS >= 70 THEN 1 ELSE 2 END),       -- higher marks first
         (CASE WHEN STUDENTS.MARKS >= 70 THEN STUDENTS.NAME END),  -- higher marks by name
         STUDENTS.MARKS

【讨论】:

  • 谢谢,这教会了我很多关于 thinks 在 SQL 中的工作原理。
【解决方案2】:

对于您使用的每个 RDBMS,SQL 都是不同的,很少有代码可以在另一个上运行,除非它非常基本并且不使用供应商特定的功能(而且 MySQL 充满了非通用行为 imo... )。您必须满足您正在使用的特定 RDBMS。

这里有 2 个问题。首先是ORDER BY 中的CASE。如果WHEN 的计算结果为真,则返回STUDENTS.NAME,如果不是STUDENTS.MARKS

STUDENTS.NAME 显然是 (n)varchar,然而,STUDENTS.MARKS 很可能是 int,因此学生的姓名将被隐式转换为 int,并且该转换将失败(惊讶,@ 987654331@ 不是有效的整数值)。看来你想要:

ORDER BY GRADES.GRADE,
         CASE STUDENTS.MARKS>=70 THEN 0 ELSE 1 END,
         STUDENTS.NAME,
         STUDENTS.MARKS;

您在SELECT 中的CASE 也有问题。 "NULL" 表示返回名为 NULL 的列的值(" 是 ANSI 分隔标识符),而不是值 NULL(或 varchar'NULL')。但是,考虑到 CASE 返回 NULL 如果没有表达式返回 true,您实际上可以完全删除 ELSE 子句。

【讨论】:

  • 感谢您的时间和解释,这对我也很有帮助。
【解决方案3】:

错误的原因是,CASE 表达式在所有情况下都应该具有相同的数据类型。

您下面的代码是问题所在。它有 Student.Name,即 Priya,它是一个字符字段。 Students.Marks 是整数字段,您有问题。

     (CASE
             WHEN (STUDENTS.MARKS>=70) THEN  STUDENTS.NAME
             ELSE  STUDENTS.MARKS
             END) ;

你要做的是,你必须有相同的数据类型。

   (CASE
             WHEN (STUDENTS.MARKS>=70) THEN  STUDENTS.NAME
             ELSE  CAST(Students.MARKS AS VARCHAR(30))
             END) ;

【讨论】:

  • 非常感谢,对于您的解释,我确实从您那里学到了很多东西,我对此很陌生,并试图通过解决问题来学习并在这个问题上浪费了很多时间,因为我知道我的方法是对的。
猜你喜欢
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
相关资源
最近更新 更多