【问题标题】:SQL how to create detail table from summary tableSQL如何从汇总表创建明细表
【发布时间】:2012-08-30 17:11:33
【问题描述】:

现在我有一个这样的游戏总结表:

我想将“开始时间”和“结束时间”按小时拆分,并将其转换为以下详细外观:

它有点类似于 Unpivot,但不完全相同。 sql语句应该怎么写?非常感谢!

【问题讨论】:

  • What have you tried? 如果您发布您尝试过的内容,人们通常会更愿意提供帮助。我们不想为他们做别人的工作,但如果您尝试过的 SQL 中有一些东西卡住了,我们会提供帮助。
  • 您使用的是什么 RDBMS 和版本?
  • 我使用的是 SQL Server 2008,谢谢!!
  • 我尝试使用变量来计算一条记录可能需要重复的次数。但我不知道如何自动插入更改的记录。另外,我需要稍后删除该变量,因为 SSAS 不允许将变量用作 T-SQL

标签: sql row summary unpivot


【解决方案1】:

在 PostgreSQL 中是:

SELECT PlayerID
     , generate_series(s.StartTime, s.EndTime - 1) AS StartTimeCol
     , generate_series(s.StartTime + 1, s.EndTime) AS EndTimeCol
FROM summaryTable s

在这个Link 中,您可以看到如何将generate_series 函数添加到SQL Server 2008

查看实际操作Here

【讨论】:

    【解决方案2】:

    如果您使用的是 SQL Server,则可以尝试以下 TSQL 块。它使用游标遍历开始和结束时间之间超过 1 小时的行,并进行迭代,将各个“小时”添加到 @gamesTable 表变量中。

    一旦游标完成并将记录填充到@gamesTable 变量中,针对原始表的那些在开始时间和结束时间之间有 1 小时或更短时间的行的 SELECT 语句将联合到存储到 @gamesTable 中的所有行游戏桌。

    DECLARE Game_Cursor CURSOR FOR
        SELECT *
        FROM summaryTable
        WHERE EndTime - StartTime > 1
    
    OPEN Game_Cursor;
    DECLARE @PlayerID char
    DECLARE @StartTime int
    DECLARE @EndTime int
    DECLARE @TempEndTime int
    DECLARE @gamesTable TABLE(PlayerID char, StartTime int, EndTime int)
    
    --Fetch the first row
    FETCH NEXT FROM Game_Cursor INTO @PlayerID, @StartTime, @EndTime
    WHILE @@FETCH_STATUS = 0
    BEGIN
            WHILE (@EndTime - @StartTime) > 0
            BEGIN
                SET @TempEndTime = @StartTime + 1
                INSERT INTO @gamesTable
                    SELECT @PlayerID AS PlayerID, @StartTime AS StartTime, @TempEndTime AS EndTime
    
                SET @StartTime = @StartTime + 1
            END;
    
            --Fetch the next row
            FETCH NEXT FROM Game_Cursor INTO @PlayerID, @StartTime, @EndTime
    END;
    
    --Rid of the cursor
    CLOSE Game_Cursor;
    DEALLOCATE Game_Cursor;
    
    --Output the results
    SELECT * FROM summaryTable WHERE (EndTime - StartTime) <= 1
    UNION ALL
    SELECT * FROM @gamesTable
    

    【讨论】:

    【解决方案3】:

    在 SQL Server 2005+ 中,您可以使用 CTE 来获取结果:

    ;with cte (playerid, starttime, endtime) as 
    (
      select playerid, min(starttime) starttime, max(endtime) endtime
      from yourtable
      group by playerid
      union all
      select playerid, starttime + 1, endtime
      from cte
      where starttime < endtime
    )
    select playerid,
      starttime,
      case 
        when starttime + 1 < endtime
        then starttime + 1
        else endtime
      end endtime
    from cte
    where starttime != endtime
    order by playerid, starttime
    

    SQL Fiddle with Demo

    【讨论】:

      猜你喜欢
      • 2014-01-08
      • 1970-01-01
      • 2013-03-29
      • 2023-04-03
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      相关资源
      最近更新 更多