【问题标题】:How do I sum up video game scores for multiple students in SQL?如何在 SQL 中总结多个学生的视频游戏分数?
【发布时间】:2014-12-12 16:08:18
【问题描述】:

我有 3 列数据。第 1 列是学生的姓名,第 2 列是他们玩的游戏的名称。他们可以玩 10 种可能的游戏,并简称为游戏 1 到游戏 10'。第 3 列包含学生在游戏中获得的分数,它可能是正数或负数。学生可以玩 10 场比赛中的任何一场比赛 0 次到多次(无限制)。每次学生玩任何游戏时,都会创建一行数据。

我想总结学生在 10 场比赛中的任何一场比赛中获得的所有分数,按学生排序。因此,行标题将是学生姓名,列标题将是游戏名称(游戏 1 到游戏 10)。

这是我一直在做的代码:

SELECT [STUDENT],

SUM ( [SCORE]) 
FROM [Students].[dbo].GameScores
WHERE [GAME] = 'GAME 1'  --swap in the game name that you want

GROUP BY [STUDENT]

我为 10 场比赛中的每场运行上述代码 10 次,将第 1 场比赛换成第 2 场比赛,然后是第 3 场比赛,依此类推。然后我会根据需要手动将结果剪切并粘贴到 Excel 中。随着游戏数量的增加(达到 100 个),我显然不想运行上面的代码来手动提取所有 100 个游戏的得分总和。

如何更改上述查询,以便可以遍历所有 10 场比赛(或任意 X 场比赛,也许 X 等于 100)并显示结果,以便行标题是学生姓名,列标题是游戏名称,并且单元格包含学生在特定游戏中的得分总和(这可以是负数或正数)。

我使用的是 SQL Server 2008 R2。

【问题讨论】:

  • 您需要在查询中添加[GAME],然后您需要在结果中添加PIVOT。这里有大量关于旋转的信息。或者你可以让你的表现层为你做这件事。
  • 当您说我需要在查询中添加 [GAME] 时,您能告诉我您的意思吗?我目前在查询中定义了 [GAME],但我不知道如何遍历所有 10 场比赛或任意 X 场比赛(其中 X 可以等于 100)。
  • SELECT GAME,STUDENT,SUM(SCORE) from ... GROUP BY GAME,STUDENT 开头。这将为您提供您正在寻找的内容。如果您想查询游戏的子集,只需将它们添加到您的 where 子句中即可。

标签: sql sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:

这个怎么样:

SELECT student, [Game 1], [Game 2], [Game 3]
FROM Students.dbo.GameScores g
PIVOT (SUM(Score) FOR Game IN ([Game 1], [Game 2], [Game 3])) pvt

您可以在示例中添加游戏 4 到 10 以满足您的要求。

【讨论】:

    【解决方案2】:
    create table #temp (student varchar(24), score int, Gametitle varchar(20))
        insert into #temp (student , score , Gametitle )
        values
        ('Student1', 100, 'Game1')
        ,('Student1', 90, 'Game2')
        ,('Student1', 80, 'Game3')
        ,('Student2', 100, 'Game1')
        ,('Student2', 100, 'Game2')
        ,('Student2', 100, 'Game3')
        ,('Student3', 100, 'Game1')
        ,('Student3', 50, 'Game4')
        ; 
    
    select 
        student 
        ,[Game1], [Game2], [Game3],[Game4]
    
    
    
    
    from 
    #temp
    
    
    pivot (
    
        sum(score)
            for Gametitle in ([Game1], [Game2], [Game3],[Game4])) as pivottable
    
            drop table #temp
    

    结果看起来像

    student |   Game1|  Game2|  Game3|  Game4|
    Student1|   100  |    90 |    80 |   NULL|
    Student2|   100  |   100 |    100|   NULL|
    Student3|   100  |   NULL|   NULL|   50  |
    

    如果由于某种原因您不想输入所有游戏名称,请尝试此操作

    create table #temp (student varchar(24), score int, Gametitle varchar(20), league varchar(20))
    insert into #temp (student , score , Gametitle,league )
    values
    ('Student1', 100, 'Game1','silver')
    ,('Student1', 90, 'Game2','silver')
    ,('Student1', 80, 'Game3','silver')
    ,('Student2', 100, 'Game1','silver')
    ,('Student2', 100, 'Game2','silver')
    ,('Student2', 100, 'Game3','silver')
    ,('Student3', 100, 'Game1','silver')
    ,('Student3', 50, 'Game4','silver')
    ,('Student1', 50, 'Game1','silver')
    
    
    ; 
    
    declare @columns nvarchar(max)
    
    select @columns = Coalesce(@columns + ',['+ [Gametitle]+']', '[' + [Gametitle] +']') 
                    from (select distinct Gametitle from #temp) columns
                    order by Gametitle
    
    declare @query nvarchar (max)
    
    set @query ='
    select 
    
         *
    
    
    
    from 
    #temp
    
    
    pivot (
    
        sum(score)
            for Gametitle in (' + @columns + '))pv
    
    
    
            '
    
            exec sp_executesql @query
    
            drop table #temp
    

    【讨论】:

      【解决方案3】:

      您想要的是将垂直表格转换为水平表格。对此的解决方案是PIVOT显式或隐式定义。

      如果您希望查询是完全动态的(不是向查询中添加新游戏,而是查询将自行处理),您将需要使用动态 SQL 来分析您的数据并准备数据透视包括所有字段的查询,如下所示:

      /* parameters' definition and initializing */
      declare @sql nvarchar(max), @columns nvarchar(max);
      set @columns = '';
      
      /* Get the unique list of played games */
      select @columns = columns + quotename(Game) + ','
      from
      (
          select distinct Game
          from Students.dbo.Games        
      ) x
      order by Game; /* this will place the payed games in the alphabetical order */
      
      set @columns = left(@columns, len(@columns) - 1); /* to remove last coma */
      
      /* Preparing dynamic SQL based on the played games */
      set @sql = 'SELECT student, ' + @columns'
      FROM Students.dbo.GameScores g
      PIVOT (SUM(Score) FOR Game IN (' + @columns + ')) pvt';
      
      /* Executing the dynamic SQL */
      exec sp_executesql @sql;
      

      【讨论】:

        猜你喜欢
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多