frontin
frontin

Reputation: 753

Pivoting SQL Server result set

if I have a result returned as follows:

pkTestInstanceID    Percent1    Count1    Percent2    Count2
1                   25          1         75          3
2                   50          2         50          2

Is there a way so it pivots in such format:

pkTestInstanceID   Percent     Count
1                  25          1
1                  75          3
2                  50          2
2                  50          2

Sorry if this question is totally misguided. I'm not super clear on the pivoting process. Thanks for any help. EDIT I should probably have noted that the Percent1, Count1, Percent2 etc columns are created based off of another column (stackposition). So if stackposition has 4 rows then the percent and count will go up to percent4 count4. Is a pivot or union still possible without the knowledge of the exact number of percent and count columns in the result set.

EDIT 2: It gets a bit more complicated now...

I now realize that I have to include another item in my select statement (fkBandID). For each bandID there is a stackposition as stated above, so for bandID 96 the stackposition is 4, for 97 the stackposition is 3, for 98 the stackposition is 2 etc. so I want the result set to look as follows:

fkBandID    pkTestInstanceID  Band_Percent    Band_Count     StackPosition (not included but there for for visual example)
96          265               2                1             4
97          265               4                2             3
98          265               34              17             2
99          265               59              29             1    

Here is what the creation of my second query looks like after the initial result set is brought back and with the bandID being selected including the new bandID. This is from Pradeep's answer. http://gyazo.com/091ece1a4a1334c0f2546bccb8a6b8da

This is what the result set looks like, so as you can see there are 4 rows being created for each bandID. Is there anyway to fix this and make it look as I displayed above in the cross apply that Pradeep helped me with? Or any other solution? http://gyazo.com/cd19634a1201362ac3aa4546f15373c9

Sorry I'm super nooby with SQL. Let me know if more info is needed.

EDIT 3

(N'DECLARE @strYearIds nvarchar(100)
              SET @strYearIds = ''' + @strYearIds + N'''
            DECLARE @strDemoCodeIds nvarchar(100)
              SET @strDemoCodeIds = ''' + @strDemoCodeIds + N'''
             DECLARE @intRosterSetId int
               SET @intRosterSetId = ' + CONVERT(nvarchar, @intRosterSetId) + N'
             DECLARE @intSchoolId int
               SET @intSchoolId = ' + CONVERT(nvarchar, @intSchoolId) + N'
             DECLARE @intTeachId int
               SET  @intTeachId = ' + CONVERT(nvarchar, @intTeachId) + N'
             DECLARE @intGradeId int
               SET @intGradeId = ' + CONVERT(nvarchar, @intGradeId) + N'
             DECLARE @intDeptId int
               SET @intDeptId = ' + CONVERT(nvarchar, @intDeptId) + N'
             DECLARE @intCourseId int
               SET @intCourseId = ' + CONVERT(nvarchar, @intCourseId) + N'
             DECLARE @intPeriodId int
               SET @intPeriodId = ' + CONVERT(nvarchar, @intPeriodId) + N'
             DECLARE @strTestInstId nvarchar(100) 
               SET @strTestInstId = ''' + @strTestInstId + N'''
             DECLARE @intTestTypeId int
               SET @intTestTypeId = ' + CONVERT(nvarchar, @intTestTypeId) + N'
             DECLARE @strSubIds nvarchar(100)
               SET @strSubIds = ''' + @strSubIds + N'''
             DECLARE @bitIsStrand bit 
               SET @bitIsStrand = ' + CONVERT(nvarchar, @bitIsStrand) + N'
             DECLARE @intPerfLevelReportId int
               SET @intPerfLevelReportId = ' + CONVERT(nvarchar, @intPerfLevelReportId) + 



        N' DECLARE @tempTests TABLE (id int)

        INSERT INTO @tempTests
            exec SPGetStudentTests_Local_MTI @strDemoCodeIds, @strYearIds, @intSchoolId, @intTeachId, @intGradeId,
                    @intRosterSetId, @intPeriodId, @intDeptId, @intCourseId, @strTestInstId, @intTestTypeId

        DECLARE @tempSubs TABLE (id int)
        IF @bitIsStrand = 1
        BEGIN
            INSERT INTO @tempSubs
                SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID /*= @intSubID*/ IN (SELECT number FROM itot(@strSubIds, N'','')) AND fkTestTypeID = @intTestTypeId 
        END
        ELSE
        BEGIN
            INSERT INTO @tempSubs
                SELECT number FROM itot(@strSubIds, N'','')--VALUES (@intSubId)
        END

        SELECT bands.pkPerformanceLevelReportBandID AS ''fkBandID'', TestInstances.pkTestInstanceID AS ''TestInstanceID'', StudentScores_Subject.fkTest_SubjectID AS ''TestSubjectID'', '
            + @cols +   
        N'INTO ##tempTable FROM StudentScores_Subject
                INNER JOIN StudentTests ON StudentScores_Subject.fkStudentTestID = StudentTests.pkStudentTestID
                INNER JOIN TestInstances ON  TestInstances.pkTestInstanceID = StudentTests.fkTestInstanceID
                INNER JOIN CAHSEE_TestPeriods ON CAHSEE_TestPeriods.pkTestPeriodID = TestInstances.fkTestPeriodID
                INNER JOIN PerformanceLevelReportBands bands ON bands.fkPerformanceLevelReportID = @intPerfLevelReportId
                LEFT JOIN MMARS_Web_TestInfo_California.dbo.PerfLevelReportBandCutScores cutScores ON cutScores.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
                    AND cutScores.fkGradeID = @intGradeId
                    AND cutScores.fkTestSubjectID IN (SELECT id FROM @tempSubs)
                INNER JOIN PerfLevelReportBandComponents bandComponents ON bandComponents.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID 
                    AND((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue) OR 
                        ((CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN bandComponents.minScore and bandComponents.maxScore)
                          OR 
                         (CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN cutScores.minScore and cutScores.maxScore))
                        )
                RIGHT JOIN MM_SchoolYears ON MM_SchoolYears.pkSchoolYearID = TestInstances.fkSchoolYearID
        WHERE MM_SchoolYears.pkSchoolYearID IN (SELECT number FROM itot(@strYearIds, N'',''))
                AND bands.fkPerformanceLevelReportID = @intPerfLevelReportId
                AND StudentScores_Subject.fkStudentTestID IN (SELECT id FROM @tempTests)
                AND StudentScores_Subject.fkScoreTypeID = bandComponents.fkScoreTypeID
                AND StudentScores_Subject.fkTest_SubjectID IN (SELECT id FROM @tempSubs)
                --AND((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue) OR 
                    --(StudentScores_Subject.ScoreValue BETWEEN bandComponents.minScore and bandComponents.maxScore) OR 
                    --(StudentScores_Subject.ScoreValue BETWEEN cutScores.minScore and cutScores.maxScore))
        GROUP BY bands.pkPerformanceLevelReportBandID, TestInstances.pkTestInstanceID, StudentScores_Subject.fkTest_SubjectID 
        ORDER BY bands.pkPerformanceLevelReportBandID, TestInstances.pkTestInstanceID, StudentScores_Subject.fkTest_SubjectID')

The @cols variable is as follows:

DECLARE @cols NVARCHAR(MAX)
            SELECT @cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT ', SUM(CASE WHEN bands.StackPosition = ''' + STR(b.StackPosition, 1) + ''' THEN 1 ELSE 0 END) * 100.0/ CASE WHEN COUNT(pkStudentScoreID) = 0 THEN 1 ELSE COUNT(pkStudentScoreID) END AS ''Percent_' + STR(b.StackPosition, 1) + ''', SUM(CASE WHEN bands.StackPosition = ''' + STR(b.StackPosition, 1) + ''' THEN 1 ELSE 0 END) AS ''Count_' + STR(b.StackPosition, 1) + ''''
                    FROM    PerformanceLevelReportBands AS b
                    WHERE b.fkPerformanceLevelReportID = @intPerfLevelReportId
                    ORDER BY ', SUM(CASE WHEN bands.StackPosition = ''' + STR(b.StackPosition, 1) + ''' THEN 1 ELSE 0 END) * 100.0/ CASE WHEN COUNT(pkStudentScoreID) = 0 THEN 1 ELSE COUNT(pkStudentScoreID) END AS ''Percent_' + STR(b.StackPosition, 1) + ''', SUM(CASE WHEN bands.StackPosition = ''' + STR(b.StackPosition, 1) + ''' THEN 1 ELSE 0 END) AS ''Count_' + STR(b.StackPosition, 1) + ''''
                    FOR XML PATH('')
                  ), 1, 2, '')

Upvotes: 1

Views: 105

Answers (2)

Pரதீப்
Pரதீப்

Reputation: 93734

what you are looking for is Unpivot not pivot

CREATE TABLE #piv
  (
     pkTestInstanceID INT,
     Percent1         INT,
     Count1           INT,
     Percent2         INT,
     Count2           INT
  )

INSERT INTO #piv
VALUES      ( 1,25,1,75,3),
            (2,50,2,50,2)

SELECT pkTestInstanceID,
       [percent],
       [count]
FROM   #piv AS p
       CROSS APPLY ( VALUES (Percent1,Count1),
                            (Percent2,Count2)) 
       AS x([percent], [count]); 

If you want this to work dynamically then below code should help you. For example i have kept no. of stackposition rows as 2 u can change it and check

DECLARE @stackposition INT=2,
        @sql           NVARCHAR(max),
        @cnt           INT=1

SET @sql =' SELECT pkTestInstanceID,
           [percent],
           [count]
    FROM   #piv AS p
           CROSS APPLY ( VALUES '

WHILE @cnt <= @stackposition
  BEGIN
      SET @sql+='([Percent' + CONVERT(VARCHAR(10), @cnt)+ '],[Count' + CONVERT(VARCHAR(10), @cnt) + ']),'
      SET @cnt+=1
  END

SET @sql= LEFT(@sql, Len(@sql) - 1)
SET @sql+=') AS x([percent], [count])'

EXEC Sp_executesql
  @sql 

OUTPUT

pkTestInstanceID    percent  count
----------------    -------  -----
  1                  25        1
  1                  75        3
  2                  50        2
  2                  50        2

Upvotes: 2

Rahul
Rahul

Reputation: 77896

You don't really need to pivot here. You can do a UNION on the resultset as suggested by @bksi like below

select pkTestInstanceID, percent1 as [percent], count1 as count
from (
inner result set
) tab

UNION

select pkTestInstanceID, percent2, count2
from (
inner result set
) tab1    

Upvotes: 0

Related Questions