簡體   English   中英

透視SQL Server結果集

[英]Pivoting SQL Server result set

如果我返回的結果如下:

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

有沒有一種方法可以將其轉換為以下格式:

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

抱歉,這個問題完全被誤導了。 我對數據透視過程不太清楚。 謝謝你的幫助。 編輯我可能應該已經注意到,Percent1,Count1,Percent2等列是基於另一列(堆棧位置)創建的。 因此,如果stackposition有4行,則百分比和計數將上升到percent4 count4。 在不知道結果集中確切的百分比和計數列的情況下,仍然可以進行數據透視或聯合。

編輯2:現在變得更加復雜了...

現在,我意識到我必須在我的選擇語句(fkBandID)中包含另一個項目。 對於每個bandID,都有一個如上所述的堆棧位置,因此對於bandID 96,堆棧位置為4,對於97,堆棧位置為3,對於98,堆棧位置為2,依此類推,所以我希望結果集如下所示:

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    

這是在恢復初始結果集並選擇bandID包括新bandID之后創建第二個查詢的樣子。 這是來自Pradeep的回答。 http://gyazo.com/091ece1a4a1334c0f2546bccb8a6b8da

這就是結果集的樣子,因此您可以看到為每個bandID創建了4行。 無論如何,有什么辦法可以解決這個問題,並使它看起來像我在十字架上顯示的那樣,適用於Pradeep幫助我的應用? 或其他解決方案? http://gyazo.com/cd19634a1201362ac3aa4546f15373c9

抱歉,我對SQL非常滿意。 讓我知道是否需要更多信息。

編輯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')

@cols變量如下:

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, '')

您正在尋找的是Unpivot不樞軸

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]); 

如果您希望它動態地工作,那么下面的代碼應該可以為您提供幫助。 例如,我一直沒有。 的stackposition行為2 u可以更改它並檢查

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

您實際上並不需要在這里pivot 您可以按如下所示由@bksi建議在結果集上執行UNION

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

UNION

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM