关于sql server:SQL Case Statement numeric and varchar

SQL Case Statement numeric and varcha

SQL

我想将小学分配给 9 年级以下和 9 年级及以上的学年,而 Preschool 是相同的


请尝试以下...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SELECT Student_Subject_Type_Desc,
       Class_Year,
       CASE
           WHEN Class_Year = 'PreSchool' THEN
               'PreSec'
           WHEN Class_Year = 'Voc Yr1' THEN
               'Voc_Yr1'
           WHEN Class_Year = 'Voc Yr2' THEN
               'Voc_Yr2'
           WHEN ISNUMERIC( Class_Year ) <> 1 THEN
               NULL
           WHEN CAST( Class_Year AS INT ) < 9 THEN
               'Primary'
           ELSE
               'Secondary'
       END AS SchType
FROM FILNA.dbo.VIEW_FILNA_STUDENTS_SUBJECT
ORDER BY Student_Subject_Type_Desc
LIMIT 1000

CASE 语句基于由字符串值组成的Class_Year。此值将等效于一个数字、几个可接受的字符串之一(即 PreSchoolVoc Yr1Voc Yr2),或者在某些方面无效。

我首先测试了 Class_Year 是否等于可接受的字符串之一。消除这些可能性后,测试 Class_Year 的值是否代表一个数字变得更加容易。我使用 ISNUMERIC( Class_Year ) <> 1 来测试 Class_Year 是否不代表数字并在这种情况下返回值 NULL。如果 Class_Year 的值确实表示一个数字,则根据该数字的值返回 PrimarySecondary,这是我通过将 Class_Year 的值转换为 INT 获得的。

请注意,从您的问题中不清楚如何处理 0Class_Year 值、负数、太大的数字和非整数等效实数,所以我假设它们不会发生或不会发生需要进行测试。如果确实需要对其进行测试,请修改您的问题以说明这一点。另外,如果您希望我测试太大的数字,请说明最大有效数字是多少。

附录

至于您第二条评论中的第二条语句,您提供的代码是...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SELECT Student_Subject_Type_Desc,
       Class_Year,
       CASE
           WHEN Class_Year = 'PreSchool' THEN
               'PreSec'
           WHEN Class_Year = 'Voc Yr1' THEN
               'Voc_Yr1'
           WHEN Class_Year = 'Voc Yr2' THEN
               'Voc_Yr2'
           WHEN ISNUMERIC( Class_Year ) <> 1 THEN
               NULL
           WHEN CAST( Class_Year AS INT ) < 9 THEN
               'Primary'
           ELSE
               'Secondary'
       END AS SchType
FROM [FILNA].[dbo].[Student_Subject_Desc]
WHERE SchType = 'Primary'
ORDER BY Student_Subject_Type_Desc

因为 SchType 是我们使用 CASE 语句从应用 WHERE 子句后允许的字段创建的字段,所以我们的 WHERE 子句将无法引用它。解决此问题的一种方法是将我的回答开头的语句用作 SELECT 语句的子查询,该语句将返回受 WHERE 子句约束的所有字段。例如...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SELECT Student_Subject_Type_Desc,
       Class_Year,
       SchType
FROM ( SELECT Student_Subject_Type_Desc,
              Class_Year,
              CASE
                  WHEN Class_Year = 'PreSchool' THEN
                      'PreSec'
                  WHEN Class_Year = 'Voc Yr1' THEN
                      'Voc_Yr1'
                  WHEN Class_Year = 'Voc Yr2' THEN
                      'Voc_Yr2'
                  WHEN ISNUMERIC( Class_Year ) <> 1 THEN
                      NULL
                  WHEN CAST( Class_Year AS INT ) < 9 THEN
                      'Primary'
                  ELSE
                      'Secondary'
              END AS SchType
       FROM FILNA.dbo.VIEW_FILNA_STUDENTS_SUBJECT
     ) AS SchTypeFinder
WHERE SchType = `Primary`
ORDER BY Student_Subject_Type_Desc
LIMIT 1000

但是,这比将语句更改为这种形式效率低...

1
2
3
4
5
6
7
8
SELECT Student_Subject_Type_Desc,
       Class_Year,
       'Primary' AS SchType
FROM [FILNA].[dbo].[Student_Subject_Desc]
WHERE ISNUMERIC( Class_Year ) = 1
  AND CAST( Class_Year AS INT ) < 9
ORDER BY Student_Subject_Type_Desc
LIMIT 1000

这只会 SELECT 记录其中 Class_Year 表示小于 9 的数字,即只有那些符合 SchType = 'Primary' 条件的记录。这消除了对 CASE 语句的任何需求,并使我们能够始终为 SchType 返回 Primary

如果您有任何问题或意见,请随时发表相应的评论。

进一步阅读

使用 sql 查询将字符串转换为 int(关于将字符串转换为 INT)

https://docs.microsoft.com/en-us/sql/t-sql/functions/isnumeric-transact-sql(关于 ISNUMERIC() 函数)