sql >> データベース >  >> RDS >> Sqlserver

SQL Server 2005 の動的列を使用したクロス集計クエリ

    PIVOT を実行するには 2 つの方法があります 値をハードコーディングする場合は静的、実行時に列が決定される場合は動的です。

    動的なバージョンが必要な場合でも、静的な PIVOT から始める方が簡単な場合があります そして、動的なものに向けて取り組みます。

    静的バージョン:

    SELECT studentid, name, sex,[C], [C++], [English], [Database], [Math], total, average
    from 
    (
      select s1.studentid, name, sex, subjectname, score, total, average
      from Score s1
      inner join
      (
        select studentid, sum(score) total, avg(score) average
        from score
        group by studentid
      ) s2
        on s1.studentid = s2.studentid
    ) x
    pivot 
    (
       min(score)
       for subjectname in ([C], [C++], [English], [Database], [Math])
    ) p
      

    デモによる SQL Fiddle を参照してください

    変換される値がわからない場合は、動的 SQL を使用できます。

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT distinct ',' + QUOTENAME(SubjectName) 
                        from Score
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    
    
    set @query = 'SELECT studentid, name, sex,' + @cols + ', total, average
                  from 
                 (
                    select s1.studentid, name, sex, subjectname, score, total, average
                    from Score s1
                    inner join
                    (
                      select studentid, sum(score) total, avg(score) average
                      from score
                      group by studentid
                    ) s2
                      on s1.studentid = s2.studentid
                ) x
                pivot 
                (
                    min(score)
                    for subjectname in (' + @cols + ')
                ) p '
    
    execute(@query)
      

    デモによる SQL Fiddle を参照してください。

    どちらのバージョンでも同じ結果が得られます。

    PIVOT がない場合は、答えを締めくくります。 関数の場合、CASE を使用してこの結果を取得できます および集約関数:

    select s1.studentid, name, sex, 
      min(case when subjectname = 'C' then score end) C,
      min(case when subjectname = 'C++' then score end) [C++],
      min(case when subjectname = 'English' then score end) English,
      min(case when subjectname = 'Database' then score end) [Database],
      min(case when subjectname = 'Math' then score end) Math,
      total, average
    from Score s1
    inner join
    (
      select studentid, sum(score) total, avg(score) average
      from score
      group by studentid
    ) s2
      on s1.studentid = s2.studentid
    group by s1.studentid, name, sex, total, average
      

    SQL Fiddle with Demo を参照してください



    1. IFまたはその近くでのPostgres構文エラー

    2. ユーザー定義リストを休止状態からOracleストアドプロシージャに渡す

    3. mysqlに対応する結果がない場合でもカウントを取得するにはどうすればよいですか?

    4. S3とaws_s3を使用してPostgresデータをRDSにインポートします