3

我怀疑这与我在 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 = 'Mathematics' 那么该语句将有效地执行与以下相同的操作:

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 生成的网格类似于下图。结果集看起来像 smae,但是背景数据将基于上面讨论的不同标准,并且会在每个单元格中产生不同的总数:

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**
4

2 回答 2

1

如果我理解得很好,除了过滤之外,您实际上可以自己处理所有任务。我的意思是,除了通过“英语/数学/其他”对结果进行分支/调节之外,您的问题在于它们几乎相同,除了它们来自不同的列并且您希望将它们统一穿线。

如果这不是您的实际问题,请原谅,但我是这样阅读/理解的。

由于几个原因(即我不知道 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

(为了整体可读性,我压缩了选择/联合部分)

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

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

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

于 2013-09-29T10:17:24.700 回答
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),并在 GROUP BY 中使用类似的子句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
于 2013-10-04T02:42:55.887 回答