3

これは、SELECT ステートメントに case ステートメントがあり、これに対して GROUP BY および ORDER BY ステートメントを実行しようとしているという事実と関係があると思われます。

2 つのテーブル間の結合に基づく結果セットがあります。1 つは、値 2c、2b、2a、3c、3b などを持つ ks2en、ks2ma、および Ks2av 列を持つ生徒のテーブルです。2 番目は、A+、A、A-、B+ などの各生徒の結果のテーブルです。 ks2en、ks2ma、および Ks2av 列がグループ化され、結果が合計され、左下にレベル、上に結果の合計のグリッドが表示されます。ただし、Ks2en、Ks2ma、および Ks2av の 3 種類のレベルは、特定の主題に基づいて結果をもたらす必要があります。

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

ks2en、ks2ma、または ks2av 列に値がない場合、group by を「No KS2」と表示したいと思います。

下部にある私のコードは、Ks2en に対して英語で非常にうまく機能しますが、Subject が英語、数学、またはその他のいずれであるかに基づいて結果を変更するロジックを考え出すのに苦労しています。

サブジェクトは、@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 が Science、Art、Technology などの他のものと等しい場合、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**
4

2 に答える 2

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
于 2013-10-04T02:42:55.887 に答える
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 つの列に再配置されたことに注意してください。ks2enとを区別することはできませんks2maが、1 つがあり、定数列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た実際のためにあなたを返します。「Physics」は「Other」と一致しないため、明らかに何にも一致しない部分をSubjectName除きます。OtherSubjectName で既知の値を確認し、「その他」に設定することで、簡単に解決できます。または他のもの。

ポイントは、その予備的なフィルター記述と接着剤のおかげで、データを好きなように再形成し、実際に必要なものに簡単にグループ化/投影できることです。

編集: sql2008 レベルで存在するかどうかはわかりませんが、列 <-> 行を転置できるPIVOT/演算子も確認できると思います。UNPIVOTそれらは使い方が難しく、いくつかの制限があり、実際よりもはるかに便利ではありませんが、確認する価値があります。もちろん、私があなたの問題の核心をよく理解していると仮定します。そうでない場合は申し訳ありません。

于 2013-09-29T10:17:24.700 に答える