0

N列のテーブルがあります。

TABLE:
TB_SAMPLE

COLUMNS:

VALUE_A
COUNT_A
VALUE_B
COUNT_B
VALUE_C
COUNT_C
VALUE_D
COUNT_D
VALUE_E
COUNT_E
VALUE_F
COUNT_F
VALUE_G
COUNT_G
VALUE_H
COUNT_H
VALUE_I
COUNT_I

私はこのように戻りたいです:

'Value', 'Count'
A, 1 -- this is the first and the second column
B, 3 -- this is the third and the fourth column
C, 4 -- this is the fifth and sixth column

そしてそう前進します。UNION ALL句を使用して複数のselectを試しましたが、多くのレコードを返すため、それほど速くはありません。このテーブルを2列「ピボット」するためのより良い方法はありますか?

ありがとう。

4

3 に答える 3

3

これは、次のステートメントを使用CROSS APPLYして実行することもできます。VALUES

SELECT vals, counts
FROM temp t
CROSS APPLY 
(
    VALUES
        (value_a, count_a),
        (value_b, count_b),
        (value_c, count_c),
        (value_d, count_d),
        (value_e, count_e),
        (value_f, count_f),
        (value_g, count_g),
        (value_h, count_h)
) x (vals, counts);

SQL FiddlewithDemoを参照してください。

これがどのように行われるかを説明する記事があります(登録が必要です):

http://www.sqlservercentral.com/articles/CROSS+APPLY+VALUES+UNPIVOT/91234/

于 2013-02-01T14:56:15.147 に答える
1

UNPIVOTを実行してから、データをPIVOTすると、パフォーマンスが向上する可能性があります。

DECLARE @T TABLE 
(   VALUE_A INT, COUNT_A INT, VALUE_B INT, COUNT_B INT, VALUE_C INT, COUNT_C INT, VALUE_D INT, COUNT_D INT, VALUE_E INT, 
    COUNT_E INT, VALUE_F INT, COUNT_F INT, VALUE_G INT, COUNT_G INT, VALUE_H INT, COUNT_H INT, VALUE_I INT, COUNT_I INT
);
INSERT @T VALUES (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);

WITH D AS
(   SELECT  Category = SUBSTRING(B, 7, LEN(B)), [Type] = 'Value', A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([VALUE_A], [VALUE_B], [VALUE_C], [VALUE_D], [VALUE_E], [VALUE_F], [VALUE_G], [VALUE_H], [VALUE_I])
            ) upvt
    UNION ALL
    SELECT  Category = SUBSTRING(B, 7, LEN(B)), [Type] = 'Count', A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([COUNT_A], [COUNT_B], [COUNT_C], [COUNT_D], [COUNT_E], [COUNT_F], [COUNT_G], [COUNT_H], [COUNT_I])
            ) upvt
)
SELECT  *
FROM    D
        PIVOT
        (   SUM(A)
            FOR [Type] IN ([Value], [Count])
        ) pvt;

必要に応じて、システムビューに列名を照会することにより、これを動的に行うこともできます。

補遺

これは、UNIONとPIVOTではなく結合で実現できることに気づきました。PIVOT操作が削除されるため、結合のパフォーマンスが向上すると思います。どちらがデータに最適かを確認するために、両方をテストすることをお勧めします。

WITH Val AS
(   SELECT  Category = SUBSTRING(B, 7, LEN(B)), A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([VALUE_A], [VALUE_B], [VALUE_C], [VALUE_D], [VALUE_E], [VALUE_F], [VALUE_G], [VALUE_H], [VALUE_I])
            ) upvt
), Co AS
(   SELECT  Category = SUBSTRING(B, 7, LEN(B)), A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([COUNT_A], [COUNT_B], [COUNT_C], [COUNT_D], [COUNT_E], [COUNT_F], [COUNT_G], [COUNT_H], [COUNT_I])
            ) upvt
)
SELECT  val.Category,
        [Value] = val.A,
        [Count] = co.A
FROM    val
        INNER JOIN co
            ON co.Category = val.Category;
于 2013-02-01T13:06:49.870 に答える
1

これを行う別の方法があります(私があなたの質問を正しく理解している場合)

declare @table table
(
value_a varchar(10),
count_a int,
value_b varchar(10),
count_b int,
value_c varchar(10),
count_c int,
value_d varchar(10),
count_d int,
value_e varchar(10),
count_e int,
value_f varchar(10),
count_f int,
value_g varchar(10),
count_g int,
value_h varchar(10),
count_h int
)

Insert Into @table
Select  'value a',675,
        'value b',646,
        'value c',13,
        'value d',22,
        'value e',768,
        'value f',223,
        'value g',66,
        'value h',55


SELECT  vals,
        counts
FROM 
   (
    SELECT  *
   FROM @table
    ) p
UNPIVOT
   (vals FOR cols IN 
      ([value_a],[value_b],[value_c],[value_d], [value_e],[value_f],[value_g],[value_h])
)AS unpvtValues
Unpivot 
    (
        counts for counters in ([count_a],[count_b],[count_c], [count_d],[count_e],[count_f],[count_g],[count_h])
    ) as unpvtCounts
where Right(cols, 2) = right(counters, 2)

編集

動的SQLを使用する場合は、このオプションを使用できます(これにより、テーブル変数を使用する代わりに、DBに適切なテーブルが作成されます)

create  Table  dbo.TempTable
(
value_a varchar(10),
count_a int,
value_b varchar(10),
count_b int,
value_c varchar(10),
count_c int,
value_d varchar(10),
count_d int,
value_e varchar(10),
count_e int,
value_f varchar(10),
count_f int,
value_g varchar(10),
count_g int,
value_h varchar(10),
count_h int
)

Insert Into dbo.TempTable
Select  'value a',675,
        'value b',646,
        'value c',13,
        'value d',22,
        'value e',768,
        'value f',223,
        'value g',66,
        'value h',55


Declare @ValueCols varchar(max),
        @CountCols varchar(max),
        @sql varchar(max)


Select @ValueCols = Coalesce(@ValueCols + ', ','') + '[' + Column_Name +']'
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_NAME  = 'TempTable'
And COLUMN_NAME Like 'Value%'

Select @CountCols = Coalesce(@CountCols + ', ','') + '[' + Column_Name +']'
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_NAME  = 'TempTable'
And COLUMN_NAME Like 'Count%'


Set @sql = 'SELECT  vals,
        counts
FROM 
   (
    SELECT  *
   FROM dbo.TempTable
    ) p
    UNPIVOT
   (vals FOR cols IN 
      (' + @ValueCols +')
)AS unpvtValues
Unpivot 
    (
        counts for counters in (' + @CountCols + ')
    ) as unpvtCounts
where Right(cols, 2) = right(counters, 2)'


Execute (@sql)

drop table TempTable
于 2013-02-01T13:16:29.340 に答える