8

SQL Server で行を列に転置する機能はありますか (MS-Access では可能です)。この機能は MS-Access では利用できますが、SQL Server では利用できないため、私は困惑しました。この機能が SQL Server に含まれていないのは仕様によるものですか?

4

5 に答える 5

3

http://jdixon.dotnetdevelopersjournal.com/pivot_table_data_in_sql_server_2000_and_2005.htmの例は、行の値が何であるかを事前に知っている場合にのみ機能します。たとえば、カスタム属性を持つエンティティがあり、カスタム属性が子テーブルの行として実装されているとします。子テーブルは基本的に変数と値のペアであり、これらの変数と値のペアは構成可能です。

color red
size  big
city  Chicago

うまくいくテクニックを説明します。私はそれを使用しました。私はそれを宣伝していませんが、それは機能します。

事前に値がわからない場所でデータをピボットするには、列のない一時テーブルをその場で作成します。次に、カーソルを使用して行をループし、変数ごとに動的に作成された「変更テーブル」を発行します。これにより、最終的に一時テーブルに列、色、サイズ、都市が含まれるようになります。

次に、一時テーブルに1つの行を挿入し、変数と値のペアを介して別のカーソルで更新し、通常は親エンティティと結合された行を選択します。これにより、カスタムの変数と値のペアが構築されたように見えます。元の親エンティティの列にあります。

于 2008-09-30T13:13:23.923 に答える
2

説明されているカーソル メソッドは、おそらく最も SQL に似ていません。前述のように、SQL 2005 以降には PIVOT があり、うまく機能します。ただし、古いバージョンと非 MS SQL サーバーの場合は、「Optimzing Transact-SQL」の Rozenshtein メソッド (編集: 絶版ですが、Amazon から: http://www.amazon.com/Optimizing-Transact-SQL- Advanced-Programming-Techniques/dp/0964981203 ) は、データのピボットとアンピボットに優れています。ポイント特性を使用して、行ベースのデータを列に変換します。Rozenshtein はいくつかのケースを説明していますが、ここに 1 つの例を示します。

SELECT
    RowValueNowAColumn = 
       CONVERT(varchar,
           MAX(
          SUBSTRING(myTable.MyVarCharColumn,1,DATALENGTH(myTable.MyVarCharColumn)
       * CHARINDEX(sa.SearchAttributeName,'MyRowValue'))))
FROM
    myTable

この方法は、case ステートメントを使用するよりもはるかに効率的であり、さまざまなデータ型と SQL 実装 (MS SQL だけでなく) で機能します。

于 2008-10-04T00:19:01.940 に答える
1

この種のことについては、小規模に限定するのが最善です。ただし、SQL 2k を使用していて PIVOT 機能を使用できない場合は、その仕事を行うストアド プロシージャを作成しました。ちょっと面倒な仕事なので、好きなだけ引き離してください。以下を SQL ウィンドウに貼り付け、下部の EXEC を必要に応じて編集します。生成されているものを確認したい場合は、真ん中の --s を削除してください:

IF EXISTS (SELECT * FROM SYSOBJECTS WHERE XTYPE = 'P' AND NAME = 'USP_LIST_CONCAT')
DROP PROCEDURE USP_LIST_CONCAT
GO

CREATE PROCEDURE USP_LIST_CONCAT (@SourceTable NVARCHAR(1000) = '' ,@SplitColumn NVARCHAR(1000) = '' , @Deli NVARCHAR(10) = '', @KeyColumns NVARCHAR(2000) = '' , @Condition NVARCHAR(1000) = '')
AS
BEGIN
SET NOCOUNT ON

/* PROCEDURE CREATED 2010 FOR SQL SERVER 2000. SIMON HUGHES. */
/* NOTES: REMOVE --'s BELOW TO LIST GENERATED SQL. */

IF @SourceTable = '' OR @SourceTable = '?' OR @SourceTable = '/?' OR @SplitColumn = '' OR @KeyColumns = ''
BEGIN
PRINT 'Format for use:'
PRINT ' USP_LIST_CONCAT ''SourceTable'', ''SplitColumn'', ''Deli'', ''KeyColumn1,...'', ''Column1 = 12345 AND ...'''
PRINT ''
PRINT 'Description:'
PRINT 'The SourceTable should contain a number of records acting as a list of values.'
PRINT 'The SplitColumn should be the name of the column holding the values wanted.'
PRINT 'The Delimiter may be any single character or string ie ''/'''
PRINT 'The KeyColumn may contain a comma separated list of columns that will be returned before the concatenated list.'
PRINT 'The optional Conditions may be left blank or may include the following as examples:'
PRINT ' ''Column1 = 12334 AND (Column2 = ''ABC'' OR Column3 = ''DEF'')'''
PRINT ''
PRINT 'A standard list in the format:'
PRINT ' Store1, Employee1, Rabbits'
PRINT ' Store1, Employee1, Dogs'
PRINT ' Store1, Employee1, Cats'
PRINT ' Store1, Employee2, Dogs'
PRINT ''
PRINT 'Will be returned as:'
PRINT ' Store1, Employee1, Cats/Dogs/Rabbits'
PRINT ' Store1, Employee2, Dogs'
PRINT ''
PRINT 'A full ORDER BY and DISTINCT is included'
RETURN -1
END


DECLARE @SQLStatement NVARCHAR(4000)

SELECT @SQLStatement = '
DECLARE @DynamicSQLStatement NVARCHAR(4000)

SELECT @DynamicSQLStatement = ''SELECT '+@KeyColumns+', SUBSTRING(''

SELECT @DynamicSQLStatement = @DynamicSQLStatement + '' + '' + CHAR(10) +
'' MAX(CASE WHEN '+@SplitColumn+' = ''''''+RTRIM('+@SplitColumn+')+'''''' THEN '''''+@Deli+'''+RTRIM('+@SplitColumn+')+'''''' ELSE '''''''' END)''
FROM '+ @SourceTable +' ORDER BY '+@SplitColumn+'

SELECT @DynamicSQLStatement = @DynamicSQLStatement + '' ,2,7999) List'' + CHAR(10) + ''FROM '+ @SourceTable+''' + CHAR(10) +'''+CASE WHEN @Condition = '' THEN '/* WHERE */' ELSE 'WHERE '+@Condition END+ '''+ CHAR(10) + ''GROUP BY '+@KeyColumns+'''

SELECT @DynamicSQLStatement = REPLACE(@DynamicSQLStatement,''( +'',''('')

-- SELECT @DynamicSQLStatement -- DEBUG ONLY
EXEC (@DynamicSQLStatement)'

EXEC (@SQLStatement)

END
GO

EXEC USP_LIST_CONCAT 'MyTableName', 'ColumnForListing', 'Delimiter', 'KeyCol1, KeyCol2', 'Column1 = 123456'
于 2010-03-26T02:00:17.237 に答える
0

SQL Server 2005のUNPIVOTについて、良い記事を見つけました

columns-to-rows-in-sql-server

于 2009-04-27T06:35:57.700 に答える
0

次の形式のデータがあります

調査_質問_ID

メール (ユーザー)

答え

1 つの調査に対して 13 の質問と回答があり、私が望んでいた望ましい結果は

ユーザー--- Survey_question_ID1 --- Survey_question_ID2

メール---回答---回答 ........など

SQL Server 2000の解決策は次のとおりです。原因フィールドのデータ型はTEXTです。

DROP TABLE #tmp

DECLARE @tmpTable  TABLE
(
emailno NUMERIC,
question1 VARCHAR(80),
question2 VARCHAR(80),
question3 VARCHAR(80),
question4 VARCHAR(80),
question5 VARCHAR(80),
question6 VARCHAR(80),
question7 VARCHAR(80),
question8 VARCHAR(80),
question9 VARCHAR(80),
question10 VARCHAR(80),
question11 VARCHAR(80),
question12 VARCHAR(80),
question13 VARCHAR(8000)
)

DECLARE @tmpTable2  TABLE
(
emailNumber NUMERIC
)

DECLARE @counter INT
DECLARE @Email INT

SELECT @counter =COUNT(DISTINCT ans.email) FROM answers ans WHERE ans.surveyname=100430 AND ans.qnpkey BETWEEN 233702 AND 233714
SELECT * INTO #tmp FROM @tmpTable
INSERT INTO @tmpTable2 (emailNumber) SELECT DISTINCT CAST(ans.email AS NUMERIC) FROM answers ans WHERE ans.surveyname=100430 AND ans.qnpkey BETWEEN 233702 AND 233714

WHILE @counter >0

BEGIN

        SELECT TOP 1 @Email= emailNumber FROM @tmpTable2
        INSERT INTO @tmpTable (emailno) VALUES (@Email )


        Update @tmpTable set question1=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233702 and ans.email=@Email
        Update @tmpTable set question2=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233703 and email=@email
        Update @tmpTable set question3=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233704 and email=@email
        Update @tmpTable set question4=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233705 and email=@email
        Update @tmpTable set question5=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233706 and email=@email
        Update @tmpTable set question6=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233707 and email=@email
        Update @tmpTable set question7=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233708 and email=@email
        Update @tmpTable set question8=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233709 and email=@email
        Update @tmpTable set question9=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233710 and email=@email
        Update @tmpTable set question10=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233711 and email=@email
        Update @tmpTable set question11=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233712 and email=@email
        Update @tmpTable set question12=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233713 and email=@email
        Update @tmpTable set question13=CAST(answer as VARCHAR(8000)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233714 and email=@email

        insert into #tmp select * from  @tmpTable       

        DELETE FROM @tmpTable       
        DELETE FROM @tmpTable2 WHERE emailNumber= @Email

        set @counter =@counter -1

End

select * from #tmp
于 2010-05-24T02:52:05.293 に答える