SQL条件选择案例逻辑

时间:2013-09-26 11:52:31

标签: sql-server-2008 group-by case conditional-statements

我怀疑这与我在SELECT语句中有case语句然后我正在尝试对此执行GROUP BY和ORDER BY语句这一事实有关。

我有一个基于两个表之间的连接的结果集。一个是具有ks2en,ks2ma和Ks2av列的学生表,其值为2c,2b,2a,3c,3b等,第二个是每个学生的结果表,例如A +,A,A-,B +等。将ks2en,ks2ma和Ks2av列分组,并将结果相加,得到一个总计网格,其左下角为水平,顶部为结果。然而,Ks2en,Ks2ma和Ks2av三种类型应该根据特定主题得出结果:

 Ks2en - English Result
 Ks2ma - Maths Result
 Ks2av - Any other subject Result

如果ks2en,ks2ma或ks2av列中没有值,我希望group by显示为“No KS2”。

我底部的代码非常适合英语对抗Ks2en,但我很难根据主语是英语,数学还是其他任何东西来制定改变结果的逻辑。

通过名为@SubjectName的变量填充主题。

下面是我希望我的sql做的伪代码:

If @SubjectName = 'English' then
    If ks2en ='' then
        display 'No KS2'
    else Ks2en
    endif
Else if @SubjectName = 'Mathematics' then
    If ks2ma ='' then
        display 'No KS2'
    else Ks2ma
    endif
Else if @SubjectName <> 'English' and @SubjectName <> 'Mathematics' then
    If ks2av ='' then
        display 'No KS2'
    else Ks2av
    endif

到目前为止,我的代码是@SubjectName ='English'时的代码:

DECLARE 
@DataCollection varchar(50) = '2013/14 - Autumn 1 - Targets',
@StuYear VARCHAR(2) = '11',
@SubjectName varchar(100) ='English',
@TeachingGroup varchar(25) = 'Select All',
@SubGroup varchar(10) = 'Select All'
SELECT CASE WHEN Ks2en = '' and @SubjectName = 'English' THEN 'No KS2' ELSE ks2en END AS 'KS2',
      nullif(count(CASE WHEN result = '' THEN 1 END),0) AS 'No Level/Grade',
      nullif(count(CASE WHEN result IN ('U', '1a', '1b', '1c') THEN 1 END),0) AS '1/U',
      nullif(count(CASE WHEN result IN ('U', '2a', '2b', '2c') THEN 1 END),0) AS '2/U',
      nullif(count(CASE WHEN result IN ('G-','3c') THEN 1 END),0) AS '3c/G-',
      nullif(count(CASE WHEN result IN ('G', '3b') THEN 1 END),0) AS '3b/G',
      nullif(count(CASE WHEN result IN ('G+','3a') THEN 1 END),0) AS '3a/G+',
      nullif(count(CASE WHEN result IN( 'F-','4c') THEN 1 END),0) AS '4c/F-',
      nullif(count(CASE WHEN result IN( 'F', '4b') THEN 1 END),0) AS '4b/F',
      nullif(count(CASE WHEN result IN( 'F+', '4a') THEN 1 END),0) AS '4a/F+',
      nullif(count(CASE WHEN result IN( 'E-', '5c') THEN 1 END),0) AS '5c/E-',
      nullif(count(CASE WHEN result IN( 'E', '5b') THEN 1 END),0) AS '5b/E',
      nullif(count(CASE WHEN result IN( 'E+', '5a') THEN 1 END),0) AS '5a/E+',
      nullif(count(CASE WHEN result IN( 'D-', '6c') THEN 1 END),0) AS '6c/D-',
      nullif(count(CASE WHEN result IN( 'D', '6b') THEN 1 END),0) AS '6b/D',
      nullif(count(CASE WHEN result IN( 'D+', '6a') THEN 1 END),0) AS '6a/D+',      
      nullif(count(CASE WHEN result IN( 'C-', '7c') THEN 1 END),0) AS '7c/C-',      
      nullif(count(CASE WHEN result IN( 'C', '7b') THEN 1 END),0) AS '7b/C',     
      nullif(count(CASE WHEN result IN( 'C+', '7a') THEN 1 END),0) AS '7a/C+',         
      nullif(count(CASE WHEN result IN( 'B-', '8c') THEN 1 END),0) AS '8c/B-',  
      nullif(count(CASE WHEN result IN( 'B', '8b') THEN 1 END),0) AS '8b/B',
      nullif(count(CASE WHEN result IN( 'B+', '8a') THEN 1 END),0) AS '8a/B+', 
      nullif(count(CASE result WHEN 'A-' THEN 1 END),0) AS 'A-',
      nullif(count(CASE result WHEN 'A' THEN 1 END),0) AS 'A',
      nullif(count(CASE result WHEN 'A+' THEN 1 END),0) AS 'A+',
      nullif(count(CASE result WHEN 'A*-' THEN 1 END),0) AS 'A*-',
      nullif(count(CASE result WHEN 'A*' THEN 1 END),0) AS 'A*'
  FROM student JOIN subject 
    ON subject.upn=student.upn 
WHERE
    [StuYear] = @StuYear AND
    [DataCollection] = @DataCollection AND
    [Name] = @SubjectName AND (
        @TeachingGroup = 'Select All' OR 
        [TeachingGroup] = @TeachingGroup
    ) AND (
       @SubGroup = 'Select All' OR
       Gender = CASE 
               WHEN @SubGroup = 'GenF' THEN 'F'
               WHEN @SubGroup = 'GenM' THEN 'M'
           END
    )
 GROUP BY ks2en
 ORDER BY
    CASE WHEN ks2en = 'W' THEN 0 ELSE 1 END,
    LEFT(ks2en, 1),
    RIGHT(ks2en, 1) DESC

如果@SubjectName ='数学',那么该陈述将有效地执行与以下相同的操作:

DECLARE 
@DataCollection varchar(50) = '2013/14 - Autumn 1 - Targets',
@StuYear VARCHAR(2) = '11',
@SubjectName varchar(100) ='Mathematics',
@TeachingGroup varchar(25) = 'Select All',
@SubGroup varchar(10) = 'Select All'
SELECT CASE WHEN Ks2ma = '' and @SubjectName = 'Mathematics' THEN 'No KS2' ELSE ks2ma END AS 'KS2',
      nullif(count(CASE WHEN result = '' THEN 1 END),0) AS 'No Level/Grade',
**SNIP**
      nullif(count(CASE result WHEN 'A*' THEN 1 END),0) AS 'A*'
  FROM student JOIN subject 
    ON subject.upn=student.upn 
WHERE
    [StuYear] = @StuYear AND
    [DataCollection] = @DataCollection AND
    [Name] = @SubjectName AND (
        @TeachingGroup = 'Select All' OR 
        [TeachingGroup] = @TeachingGroup
    ) AND (
       @SubGroup = 'Select All' OR
       Gender = CASE 
               WHEN @SubGroup = 'GenF' THEN 'F'
               WHEN @SubGroup = 'GenM' THEN 'M'
           END
    )
 GROUP BY ks2ma
 ORDER BY
    CASE WHEN ks2ma = 'W' THEN 0 ELSE 1 END,
    LEFT(ks2ma, 1),
    RIGHT(ks2ma, 1) DESC

如果@SubjectName等于其他任何东西,例如科学,艺术或技术,那么SQL会想要以下内容:

DECLARE 
@DataCollection varchar(50) = '2013/14 - Autumn 1 - Targets',
@StuYear VARCHAR(2) = '11',
@SubjectName varchar(100) ='Science',
@TeachingGroup varchar(25) = 'Select All',
@SubGroup varchar(10) = 'Select All'
SELECT CASE WHEN Ks2av = '' and @SubjectName <> 'Mathematics' and @SubjectName <> 'English'  THEN 'No KS2' ELSE ks2av END AS 'KS2',
      nullif(count(CASE WHEN result = '' THEN 1 END),0) AS 'No Level/Grade',
**SNIP**
      nullif(count(CASE result WHEN 'A*' THEN 1 END),0) AS 'A*'
  FROM student JOIN subject 
    ON subject.upn=student.upn 
WHERE
    [StuYear] = @StuYear AND
    [DataCollection] = @DataCollection AND
    [Name] = @SubjectName AND (
        @TeachingGroup = 'Select All' OR 
        [TeachingGroup] = @TeachingGroup
    ) AND (
       @SubGroup = 'Select All' OR
       Gender = CASE 
               WHEN @SubGroup = 'GenF' THEN 'F'
               WHEN @SubGroup = 'GenM' THEN 'M'
           END
    )
 GROUP BY ks2av
 ORDER BY
    CASE WHEN ks2av = 'W' THEN 0 ELSE 1 END,
    LEFT(ks2av, 1),
    RIGHT(ks2av, 1) DESC

我的SQL产生的网格看起来类似于下面的。结果集看起来很糟糕,但背景数据将基于上面讨论的不同标准,并且会在每个单元格中产生不同的总数:

KS2 No Result   1/U     2/U     3c/G-   3b/G    3a/G+   4c/F-   4b/F    **snip**
No  KS2         1       NULL    NULL    NULL    NULL    NULL    NULL    **snip**
2a  NULL        NULL    NULL    NULL    NULL    NULL    2       1       **snip**
3c  1           NULL    NULL    NULL    NULL    NULL    NULL    NULL    **snip**
3b  NULL        NULL    NULL    NULL    NULL    NULL    1       NULL    **snip**
3a  1           NULL    NULL    NULL    NULL    NULL    NULL    NULL    **snip**
4c  NULL        1       1       NULL    NULL    NULL    NULL    NULL    **snip**
4b  NULL        NULL    NULL    NULL    NULL    NULL    NULL    NULL    **snip**
4a  NULL        1       1       NULL    NULL    NULL    NULL    NULL    **snip**
5c  NULL        NULL    NULL    NULL    NULL    NULL    NULL    NULL    **snip**
5b  NULL        NULL    NULL    NULL    NULL    NULL    NULL    NULL    **snip**

2 个答案:

答案 0 :(得分:1)

如果我理解得很清楚,除了过滤之外,你实际上可以自己处理任务。我的意思是,除了通过“english / math / other”分支/调整结果之外,你的问题是它们几乎完全相同,除非它们来自不同的列,你想要统一地对它们进行处理。

对不起,如果这不是你的实际问题,但我这样阅读/理解。

由于多种原因(即我不知道F + G-等级与3a 6b值的关系如何),我目前无法给出完全完整的答案,但我可以至少给你一些帮助/启动你如何解决这类问题。

你想要的效果:

     If @SubjectName = 'English' then    If ks2en ='' then    ....
else If @SubjectName = 'Maths'   then    If ks2ma ='' then    ....
else                                     If ks2av ='' then    ....

可以通过一些初步重新排列输入表来轻松完成。简单地说,只需将有趣的部分过滤成块并添加一些常量值,这些值将充当关于该块的方便元数据:

          select "English"     as topic, ks2en as ks2
          from YourTable
          where ks2en <> ''
union all
          select "Mathematics" as topic, ks2ma as ks2
          from YourTable
          where ks2ma <> ''
union all
          select "Other"       as topic, ks2av as ks2
          from YourTable
          where ks2av <> ''

请注意,我添加了一个名为topic的额外计算键值,现在这些数据重新排列为2列。您现在无法区分ks2enks2ma,但只有一个ks2,您可以通过常量topic列检测它的来源。

现在:

select
    case when subq.ks2 = '' then 'No KS2'
    else subq.ks2
    end
from
(
          select "English"     as topic, ks2en as ks2 from YourTable where ks2en <> ''
union all select "Mathematics" as topic, ks2ma as ks2 from YourTable where ks2ma <> ''
union all select "Other"       as topic, ks2av as ks2 from YourTable where ks2av <> ''
) subq
where subq.topic = @SubjectName

(为了整体可读性,我已经压缩了select / union部分)

会将KS2返回给您想要的实际SubjectName。除了显然不匹配的Other部分,因为“物理”与“其他”不匹配。您可以通过检查SubjectName中的已知值并将其设置为“其他”来轻松完成。或者别的什么。

关键是,由于初步的过滤器 - 描述和粘合它,你可以以任何你想要的方式重塑数据,然后轻松地将它分组/投影到你真正想要的东西。

编辑:我不知道它是否存在于sql2008级别,但我认为您还可以检查可以转置列&lt; - &gt;行的PIVOT / UNPIVOT运算符。它们使用起来很棘手,有一些限制使它们远不如它们那么方便,但值得检查。当然,假设我很好地理解了你的问题的核心。对不起,如果没有。

答案 1 :(得分:1)

如果我理解您的问题,您希望KS2列显示相关主题的相关KS2__数据。尝试:

CASE 
    WHEN (Ks2en = '' and @SubjectName = 'English') 
         OR (Ks2ma = '' and @SubjectName = 'Mathematics') 
         OR (Ks2av = '' and @SubjectName <> 'Mathematics' and @SubjectName <> 'English' ) 
    THEN 'No KS2' 
    ELSE CASE @SubjectName 
              WHEN 'English' THEN Ks2en 
              WHEN 'Mathematics' THEN Ks2ma 
              ELSE Ks2av 
         END
END AS KS2

您将在GROUP BY中使用此子句(减去AS KS2),并在ORDER BY中使用类似的子句:

ORDER BY
CASE WHEN
    CASE 
            WHEN (Ks2en = '' and @SubjectName = 'English') 
                 OR (Ks2ma = '' and @SubjectName = 'Mathematics') 
                 OR (Ks2av = '' and @SubjectName <> 'Mathematics' and @SubjectName <> 'English' ) 
            THEN 'No KS2' 
            ELSE CASE @SubjectName 
                      WHEN 'English' THEN Ks2en 
                      WHEN 'Mathematics' THEN Ks2ma 
                      ELSE Ks2av 
                 END
        END = 'W' THEN 0 ELSE 1 END,
    LEFT(CASE 
            WHEN (Ks2en = '' and @SubjectName = 'English') 
                 OR (Ks2ma = '' and @SubjectName = 'Mathematics') 
                 OR (Ks2av = '' and @SubjectName <> 'Mathematics' and @SubjectName <> 'English' ) 
            THEN 'No KS2' 
            ELSE CASE @SubjectName 
                      WHEN 'English' THEN Ks2en 
                      WHEN 'Mathematics' THEN Ks2ma 
                      ELSE Ks2av 
                 END
        END, 1),
    RIGHT(CASE 
            WHEN (Ks2en = '' and @SubjectName = 'English') 
                 OR (Ks2ma = '' and @SubjectName = 'Mathematics') 
                 OR (Ks2av = '' and @SubjectName <> 'Mathematics' and @SubjectName <> 'English' ) 
            THEN 'No KS2' 
            ELSE CASE @SubjectName 
                      WHEN 'English' THEN Ks2en 
                      WHEN 'Mathematics' THEN Ks2ma 
                      ELSE Ks2av 
                 END
        END, 1) DESC