9

私はこのクエリを書きました:

SELECT s, [1] AS a1, [2] AS a2, [3] AS a3, [4] AS a4
FROM (SELECT grade, aid, s FROM m) p
PIVOT
(
SUM(grade)
FOR aid IN ([1], [2], [3], [4])
) AS pvt ORDER BY pvt.s;

それは結果を返します:

s  a1  a2  a3  a4
1  25  69  95  56
2  27  99  16  87
. . . .
99 98  12  34  76

これはまさに私が望む結果です。私の問題は、「援助」に常に 4 つの異なる価値があるとは限らないことです。「a*」列の量が「aid」にある個別の値の数に依存するように、このクエリを書き直す (またはストアド プロシージャを使用する) ことは可能ですか?

4

2 に答える 2

12

必要な列のリストを取得するには、動的ピボットを使用する必要があります。これにより、最初に列のリストが取得され、次にそのリストがピボットされます。これに似たもの:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(aid) 
            FROM m 
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT s, ' + @cols + ' from 
            (
                select grade, aid, s
                from m
           ) x
            pivot 
            (
                sum(grade)
                for aid in (' + @cols + ')
            ) p 
            ORDER BY p.s'

execute(@query)
于 2012-05-29T16:59:04.350 に答える
2

Lamak:これが私が列エイリアスでそれをした方法です。エイリアスは、`aid'によってリンクされている別のテーブルの列の値にリンクされています。

DECLARE
    @cols AS NVARCHAR(MAX),
    @colsAlias AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(aid) 
    FROM m
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')

SELECT @colsAlias = STUFF((SELECT DISTINCT ',' + QUOTENAME(m.aid) + ' AS ' + QUOTENAME(n.aName)  
    FROM m INNER JOIN n ON m.aid = n.aid
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')

SET @query = 'SELECT s, ' + @colsAlias + ' FROM 
                (
                SELECT grade, aid, s
                    FROM m
                ) x

            PIVOT 
            (
                MIN(grade) FOR aid IN (' + @cols + ')
            ) p '

EXECUTE(@query)
于 2012-06-01T10:55:33.303 に答える