简体   繁体   中英

Transpose Row to Column in SQL Server 2000

I am trying to convert rows into columns in SQL Server 2000. Although all rows converted into required columns but i unable to get the value converted into the respective columns.

My code is:

DROP TABLE prePivot1
DROP TABLE results1

CREATE TABLE prePivot1 (
    [StudentId] uniqueidentifier
    , [Sub_Abbr] Varchar(100)
    , [Total_marks] MONEY
    )

CREATE TABLE results1 (
    [StudentId] uniqueidentifier
    )

INSERT INTO prePivot1
SELECT       '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'ENG', 55
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'MBEN', 90
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'ECO', 80
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'PSc', 45
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'PSY', 23

UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'ENG', 90
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'ECO', 44
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'PSc', 45
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'BST', 23
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'ASS', 80
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'PSY', 93




DECLARE @sql VARCHAR(8000)
DECLARE @pivot varchar(10)

DECLARE pivotCursor CURSOR LOCAL READ_ONLY FOR
SELECT DISTINCT
    [Sub_abbr]
FROM
    prePivot1

OPEN pivotCursor
    FETCH NEXT FROM pivotCursor INTO @pivot

    WHILE (@@FETCH_STATUS = 0) BEGIN

        SET @sql = '
        ALTER TABLE results1 ADD [' + CAST(@pivot AS VARCHAR(10))  + '] INT'
        EXEC (@sql)

        FETCH NEXT FROM pivotCursor INTO @pivot
    END
CLOSE pivotCursor

INSERT INTO results1 ([studentId])
SELECT DISTINCT [StudentId] FROM prePivot1

OPEN pivotCursor
    FETCH NEXT FROM pivotCursor INTO @pivot

    WHILE (@@FETCH_STATUS = 0) BEGIN

        SET @sql = '
        UPDATE results1
        SET
            [' + CAST(@pivot AS VARCHAR(10)) + '] = pp.[total_marks]
        FROM
            prePivot1 pp
        WHERE
            pp.[total_marks] = ' + CAST(@pivot AS VARCHAR(10)) + '
            AND pp.[studentId] = results1.[studentId]'

        EXEC (@sql)

        FETCH NEXT FROM pivotCursor INTO @pivot
    END
CLOSE pivotCursor
DEALLOCATE pivotCursor

SELECT * FROM results1

Please help me how do i do to get the expected result. Thanking you in advance.

There are a couple of things wrong with your predicate here:

pp.[total_marks] = ' + CAST(@pivot AS VARCHAR(10)) + '
  1. You are filtering on the wrong column
  2. You are not generating a proper string with the @pivot part.

This is what it looks like when you print out your dynamic sql string. Notice that it causes a join on prePivot1.total_marks column to results1.ECO column which is not what you're intending.

UPDATE
  results1
SET
  [ECO] = pp.[total_marks]
FROM
  prePivot1 AS pp
WHERE
  pp.[total_marks] = ECO
  AND pp.[studentId] = results1.[studentId]

Corrected version (you also don't need to cast the variable):

pp.[Sub_Abbr] = ''' + @pivot + '''

A slightly less error prone solution would be to parameterize your dynamic sql:

-- Change @sql --> nvarchar(4000)    
SET @sql = N'
UPDATE
  results1
SET
  ' + QUOTENAME(@pivot) + N' = pp.[total_marks]
FROM
  prePivot1 AS pp
WHERE
  pp.[Sub_Abbr] = @Sub_Abbr
  AND pp.[studentId] = results1.[studentId];';

EXEC sp_executesql
  @stmt = @sql,
  @params = N'@Sub_Abbr varchar(10)',
  @Sub_Abbr = @pivot;

This is the general pattern I've used in sql2k to pivot just for reference: (I'm assuming here that StudentId, Sub_Abbr is unique though the schema doesn't explicitly confirm this)

SELECT
  [StudentId],
  MAX(CASE WHEN [Sub_Abbr] = 'ASS' THEN [Total_marks] ELSE NULL END) AS [ASS],
  MAX(CASE WHEN [Sub_Abbr] = 'BST' THEN [Total_marks] ELSE NULL END) AS [BST],
  MAX(CASE WHEN [Sub_Abbr] = 'ECO' THEN [Total_marks] ELSE NULL END) AS [ECO],
  MAX(CASE WHEN [Sub_Abbr] = 'ENG' THEN [Total_marks] ELSE NULL END) AS [ENG],
  MAX(CASE WHEN [Sub_Abbr] = 'MBEN' THEN [Total_marks] ELSE NULL END) AS [MBEN],
  MAX(CASE WHEN [Sub_Abbr] = 'PSc' THEN [Total_marks] ELSE NULL END) AS [PSc],
  MAX(CASE WHEN [Sub_Abbr] = 'PSY' THEN [Total_marks] ELSE NULL END) AS [PSY]
FROM
  [dbo].[prePivot1]
GROUP BY
  [StudentId];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM