现在我有一个这样的游戏摘要表:
我想按小时拆分“开始时间”和“结束时间”并将其转换为以下详细外观:
它有点类似于 Unpivot,但不完全相同。sql语句应该怎么写?非常感谢!
如果您使用的是 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
在 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