繁体   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