【问题标题】:CASE expression evaluation issueCASE 表达式求值问题
【发布时间】:2016-07-18 13:15:59
【问题描述】:

我有一个 SQL 查询,它根据如下描述计算 CourseType。

   SELECT    sc.EXSJ_Description,
   sn.STEN_Student_ID , s.STUD_Forename_1, s.STUD_Surname, 
    CASE 
    WHEN sc.EXSJ_Description IN ('FUNCTIONAL SKILLS - ENGLISH (LEVEL 1 & LEVEL  2)',
    'ENGLISH (ENTRY LEVEL)', 'FUNCTIONAL SKILLS ENGLISH') THEN 'Overall'
    WHEN sc.EXSJ_Description IN ('READING -ENGLISH LEVEL 2', 'READING- ENGLISH (LEVEL 1 )', 
    'E2  ENGLISH FUNTIONAL SKILLS READING', 'E2 FUNCTIONAL SKILLS READING', 
    'E3 ENGLISH FUNTIONAL SKILLS READING')THEN 'Reading' 
    WHEN sc.EXSJ_Description IN  ('WRITING- ENGLISH (LEVEL 1 )', 'WRITING- ENGLISH LEVEL  2', 
    'E2 ENGLISH FUNCTIONAL SKILLS WRITING', 'E3 ENGLISH FUNCTIONAL SKILLS WRITING') 
    THEN 'Writing' 
    WHEN sc.EXSJ_Description IN ('SPEAKING & LISTENING- 
ENGLISH LEVEL 2', 'SPEAKING & LISTENING- ENGLISH (LEVEL 1)',
    'E3 ENGLISH FUNCTIONAL SKILLS SPEAKING AND LISTENING', 
'E2 ENGLISH FUNCTIONAL SKILLS SPEAKING AND LISTENING') 
    THEN 'Speaking & Listening' 
    END AS CourseType,
    CASE WHEN e.EXSS_Act_Grade = 'PA' THEN 'Pass' 
    WHEN e.EXSS_Act_Grade = 'FL' THEN 'Fail' 
    WHEN e.EXSS_Act_Grade = 'X' THEN 'Not Attended' END AS Grade
    FROM         
    sql10.NG.dbo.STEN AS sn
LEFT OUTER JOIN sql10.NG.dbo.EXSSexmstsbj AS e 
    ON e.EXSS_Student_ID = sn.STEN_Student_ID 
    AND sn.STEN_Provision_Code = e.EXSS_Provision_Code 
    AND sn.STEN_Provision_Instance = e.EXSS_Provision_Instance
INNER JOIN sql10.NG.dbo.STUDstudent AS s 
    ON s.STUD_Student_ID = sn.STEN_Student_ID
    INNER JOIN sql10.NG.dbo.EXSJexsubject AS sc 
    ON sc.EXSJ_Subject_Code = e.EXSS_Subject_Code
WHERE (e.EXSS_Year = '2015') 
    AND (sn.STEN_Year = '2015') 
    AND (e.EXSS_Awarding_Body IN ('13', '73')) 
    AND (e.EXSS_Provision_Code LIKE 'MA27%') 
    AND (sn.STEN_Provision_Code LIKE '27%') OR
    (sn.STEN_Provision_Code LIKE 'MA27%') 
    AND (sc.EXSJ_Description LIKE '%englis%')
    GO

所以应该有 3 种课程类型 - 总体而言,阅读或写作,但是当我执行查询时,我看到一些 NULL 值,这不是预期的。

样本数据:

CREATE TABLE [dbo].[STEN](
	[STEN_ISN] [int] IDENTITY(1,1) NOT NULL,
	[STEN_Student_ID] [char](12) NOT NULL,
	[STEN_Year] [smallint] NOT NULL,
	[STEN_Provision_Code] [char](20) NOT NULL,
	[STEN_Provision_Instance] [char](6) NOT NULL)
INSERT INTO [dbo].[STEN](
VALUES 
 (‘13068629’, ‘2015’, ‘27107’, ‘151601’),
(‘14072552   ’, ‘2015’, ‘27107’, ‘151601’),
(‘14073353’, ‘2015’, ‘27107’, ‘151601’),
(‘14073645’, ‘2015’, ‘27107/DR01’, ‘151601’),
(‘15075375’, ‘2015’, ‘27107/DR01’, ‘151601’))

CREATE TABLE [dbo].[EXSSexmstsbj](
    	[EXSS_Year] [smallint] NOT NULL,
    	[EXSS_Student_ID] [char](12) NOT NULL,
    	[EXSS_Act_Grade] [char](6) NOT NULL,
    	[EXSS_Awarding_Body] [char](16) NOT NULL,
    	[EXSS_Provision_Code] [char] (20) NULL,
    	[EXSS_Provision_Intance] [char] (6) NULL))
    INSERT INTO  dbo.EXSSexmstsbj
    VALUES  ( 2015, ‘09054118’,’PA, ‘13’, ‘MA27031/A01’, ‘151601’),
    ( 2015, ‘1261589’,’PA, ‘13’, ‘MA27031/A01’, ‘151601’),
    ( 2015, ‘1364766’,’FL, ‘13’, ‘MA27031/A01’, ‘151601’),
    ( 2015, ‘1365244’,’FL, ‘13’, ‘MA27031/A01’, ‘151601’),
    ( 2015, ‘1260791’,’X, ‘13’, ‘MA27031/A01’, ‘151601’),

CREATE TABLE [dbo].[PRPIProvisionInstance](
	[PRPI_ISN] [int] IDENTITY(1,1) NOT NULL,
	[PRPI_Code] [char](20) NOT NULL,
	[PRPI_Instance] [char](6) NOT NULL)
INSERT INTO [dbo].[PRPIProvisionInstance]
VALUES (‘19235’,’27107’,’151601’),
(‘19236’,’27107/DR01’,’151601’),
(‘19285’,‘27113’, ‘151601’),
(‘19286’,’27113/DR01’,’151601’),
(‘19237’,’27120’,’151601’)

CREATE TABLE [dbo].[PRPHProvisionHeader](
	[PRPH_Code] [char](20) NOT NULL,
	[PRPH_Title] [varchar](100) NOT NULL,
	[PRPH_ML2] [char](6) NOT NULL)
INSERT INTO [dbo].[PRPHProvisionHeader]VALUES(‘27000’,  ‘FS workshop for Art’,	‘A+D ‘),
(27000/A01’,’FS workshop for Art’,’A+D  ‘),
(‘27031/A01’,’FS English L2 (MA) (Pearson)’,’ WFD ‘),
(‘27032/A01’,’FS Maths L2 (MA) (Pearson)’,’ WFD ‘) ,
(‘27100/E91’,’EDEX English E1 FS Sept Start (13195) Tue 6.00-9.00’,’ PLW  ‘)

CREATE TABLE [dbo].[STUDstudent](
	[STUD_Student_ID] [char](12) NOT NULL,
	[STUD_Surname] [varchar](30) NOT NULL,
	[STUD_Forename_1] [varchar](20) NOT NULL,
	)	
INSERT INTO [dbo].[STUDstudent]
(‘703666V’, ‘Aakel’,’Gail’),
(‘472833M’,’Abbott’,’Emma’),
(‘481691M’,’Abbasi’,’Anisa’),
‘13072746’,’Ababio’,’Anita’),
‘13070877’,’Aaronson’,	‘Fay’)

CREATE TABLE [dbo].[EXSJexsubject](
	[EXSJ_Description] [varchar](100) NOT NULL,
	[EXSJ_Awarding_Body] [char](16) NOT NULL,
	)
INSERT INTO [dbo].[EXSJexsubject]
VALUES (‘E1  ENGLISH FUNCTIONAL SKILLS SPEAKING AND LISTENING’,	‘13‘),
(‘E1 ENGLISH FUNTIONAL SKILLS READING’,’ 13 ‘),
(‘E1 ENGLISH FUNCTIONAL SKILLS WRITING’,’ 13 ‘),        
(‘E2 ENGLISH FUNCTIONAL SKILLS SPEAKING AND LISTENING’,’13’),              
(‘E2  ENGLISH FUNTIONAL SKILLS READING’,’ 13 ‘)             

CREATE TABLE [dbo].[GNUCustom](
	[GNUC_Type] [char](4) NOT NULL,
	[GNUC_Entity_ISN] [int] NOT NULL,
GNUC_Text_1 [VARCHAR] (100) NOT NULL)

INSERT INTO VALUES
(PRPI	571	
PRPI	7761	
PRPI	8292	
PRPI	8346	
PRPI	8374	
)

请提出我哪里出错了。

谢谢, 阿尔

【问题讨论】:

  • 您的所有条件都失败并且没有else 条件,因此不满足任何条件的行将获得nulls
  • 看看你的SQL:这是一个错字...E2 ENGLISH FUNTIONAL SKILLS READING错过了C,与E3...相同:-)
  • case 表达式,而不是 case 语句...
  • 我们既没有您的表格也没有您的数据,您希望我们诊断为什么查询没有按您的预期工作?请尝试将您的查询修剪到问题的重要部分,同样为我们提供修剪后的查询将使用的最小表结构(理想情况下为CREATE 语句)和一些示例数据(理想情况下如INSERT 语句)以及您的预期输出是什么。
  • sc.EXSJ_Description & e.EXSS_Act_Grade 是否都包含大写或小写数据??

标签: sql sql-server-2008 count group-by case


【解决方案1】:

我猜 EXSJ_Description 列中还有一些其他值没有在您的 CASE WHEN 语句中被提取。

试试这个命令看看它是否返回任何非空值:

SELECT  
     EXSJ_Description
FROM 
     sql10.NG.dbo.EXSJexsubject
WHERE 
     EXSJ_Description
     NOT IN 
         ('FUNCTIONAL SKILLS - ENGLISH (LEVEL 1 & LEVEL  2)',
         'ENGLISH (ENTRY LEVEL)',
         'FUNCTIONAL SKILLS ENGLISH',
         'WRITING- ENGLISH (LEVEL 1 )',
         'WRITING- ENGLISH LEVEL  2',
         'E2 ENGLISH FUNCTIONAL SKILLS WRITING',
         'E3 ENGLISH FUNCTIONAL SKILLS WRITING',
         'SPEAKING & LISTENING- ENGLISH LEVEL 2',
         'SPEAKING & LISTENING- ENGLISH (LEVEL 1)',
         'E3 ENGLISH FUNCTIONAL SKILLS SPEAKING AND LISTENING',
         'E2 ENGLISH FUNCTIONAL SKILLS SPEAKING AND LISTENING')

如果有,请将它们添加到您的条件中。未来,最佳实践要求始终使用 ELSE 来捕获任何不匹配的值。

如果它们都为空,则您的连接可能会导致数据重复,从而产生额外的空值。没有您的数据集,很难确定。

【讨论】:

    【解决方案2】:

    试试这个,但从性能角度来看并不好

    CASE
        WHEN REPLACE(sc.EXSJ_Description,' ','') IN (
                            REPLACE('FUNCTIONAL SKILLS - ENGLISH (LEVEL 1 & LEVEL  2)',' ',''),
                            REPLACE('ENGLISH (ENTRY LEVEL)',' ',''),
                            REPLACE('FUNCTIONAL SKILLS ENGLISH',' ','')
                        ) THEN 'Overall'
        WHEN REPLACE(sc.EXSJ_Description,' ','') IN (
                           REPLACE('READING -ENGLISH LEVEL 2',' ',''),
                           REPLACE('READING- ENGLISH (LEVEL 1 )',' ',''), 
                           REPLACE('E2  ENGLISH FUNTIONAL SKILLS READING',' ',''),        
                           REPLACE('E2 FUNCTIONAL SKILLS READING',' ','') 
                           REPLACE('E3 ENGLISH FUNTIONAL SKILLS READING',' ','')
                       )THEN 'Reading' 
        WHEN REPLACE(sc.EXSJ_Description,' ','') IN  (
                           REPLACE('WRITING- ENGLISH (LEVEL 1 )',' ',''),
                           REPLACE('WRITING- ENGLISH LEVEL  2',' ',''), 
                           REPLACE('E2 ENGLISH FUNCTIONAL SKILLS WRITING',' ',''), 
                           REPLACE('E3 ENGLISH FUNCTIONAL SKILLS WRITING',' ','')
                       )THEN 'Writing' 
        ...
        ...
    

    【讨论】:

      【解决方案3】:

      尽管在某些情况下可能需要使用完全匹配,但拥有完全匹配列表会为输入错误提供机会,并且可能会导致将来出现维护问题。

      您可以考虑在此处使用模式匹配以使代码更易于理解:

      (CASE WHEN sc.EXSJ_Description LIKE 'FUNCTIONAL%' OR 
                 sc.EXSJ_Description LIKE '%ENTRY%'
           THEN 'Overall'
           WHEN sc.EXSJ_Description LIKE '%READING%'
           THEN 'Reading' 
           WHEN sc.EXSJ_Description LIKE '%WRITING%'
           THEN 'Writing' 
           WHEN sc.EXSJ_Description LIKE '%SPEAKING%LISTENING%'
           THEN 'Speaking & Listening' 
           ELSE 'Unknown'
      END) AS CourseType,
      

      诚然,这不适用于所有命名约定(如果描述同时具有READINGWRITING,那又如何呢?)。但它确实适用于您的特定名称集,并且减少了导致您原来的问题的拼写错误的机会。

      【讨论】:

      • 虽然这可能会解决问题,但它有可能导致编码错误。仅从这些值中,我们就可以看到它们具有重叠的关键字,因此过于宽泛的LIKE 条件可能会导致值被放置在它们不属于的类别中。
      猜你喜欢
      • 2011-06-12
      • 2016-11-16
      • 1970-01-01
      • 2017-06-20
      • 1970-01-01
      • 2016-07-28
      • 2018-11-03
      • 2020-07-03
      • 2020-08-06
      相关资源
      最近更新 更多