我正在尝试在描述中断的表中获取行,并通过计算的时间范围将它们分成单独的行,以插入到另一个表中,以描述每个给定范围中的每小时时间段。
以下代码为我们提供了以下输出:
我们从这一行开始(原始数据):
OutageDate StartTime EndTime Duration
2010-11-10 16:00:00.0000000 17:30:00.0000000 90
在我运行存储过程之后(这是期望的输出!我只需要知道如何将其保存到表中):
OutageDate StartHour StartMinutes EndHour EndMinutes StartTime EndTime Duration
2010-11-10 16 0 17 0 16:00:00.0000000 17:30:00.0000000 90
2010-11-10 17 30 18 0 16:00:00.0000000 17:30:00.0000000 90
以下是我需要弄清楚如何在我想要的时间值之间拆分行时保存到表中的代码。我无法控制为什么会发生这种情况,它只需要按照比我更高的人的要求并以这种格式指定:
--First, let's look at the original data in the table...just one row will do
SELECT TOP (1) *
FROM actualTable
ORDER BY OutageDate ASC
--Begin sproc logic
declare @OutageDate date
declare @StartTime time(7)
declare @EndTime time(7)
declare @StartHour bigint
declare @EndHour int
declare @StartMinute int
declare @EndMinute int
declare @Duration int
declare @Temp_StartTime time
declare @Temp_EndTime time
declare @temp_StartHour int
declare @temp_EndHour int
declare @temp_StartMinute int
declare @temp_EndMinute int
SELECT TOP(1) @OutageDate = OutageDate, @StartTime = StartTime, @EndTime = EndTime, @Duration = Duration FROM actualTable
SET @Temp_StartTime=@StartTime
SET @Temp_EndTime=@EndTime
SET @temp_StartHour=DATEPART(HOUR, @StartTime)
SET @temp_EndHour=DATEPART(HOUR, @EndTime)
SET @temp_StartMinute=DATEPART(MI, @StartTime)
SET @temp_EndMinute=DATEPART(MI, @EndTime)
PRINT @temp_StartHour
PRINT @temp_EndHour
PRINT @temp_StartMinute
PRINT @StartTime
PRINT @EndTime
if(@temp_EndMinute>0)
BEGIN
SET @temp_EndHour=@temp_EndHour+1
END
--this declares the temp table
DECLARE @Temp_Table TABLE
(
OutageDate date,
StartHour int,
StartMinute int,
EndHour int,
EndMinute int,
StartTime time,
EndTime time,
Duration int
)
--Here's the loop that inserts the rows
While((@temp_EndHour-@temp_StartHour>1))
BEGIN
INSERT INTO @Temp_Table
SELECT
@OutageDate AS OutageDate,
(DATEPART(HOUR, @Temp_StartTime)) AS StartHour,
(DATEPART(MINUTE, @Temp_StartTime)) AS StartMinute,
@temp_StartHour+1 AS EndHour,
0 AS EndMinute,
@StartTime as StartTime,
@EndTime as EndTime,
@Duration AS Duration
--DATEADD returns a specified date with the specified number interval (signed integer) added to a specified datepart of that date.
SET @temp_StartHour=@temp_StartHour+1
SET @Temp_StartTime=DATEADD(HOUR,1,@Temp_StartTime)
--Let's make sure we account for the minutes in the first and last hours if any
if(DATEPART(MI, @Temp_StartTime)!=0)
BEGIN
SET @Temp_StartTime=DATEADD(MI,-@Temp_StartMinute,@Temp_StartTime)
END
END
--Ok, if we're at the last row insertion, we still need the minutes the outage finished at...those go into StartMinutes
WHile((@temp_EndHour-@temp_StartHour=1))
BEGIN
INSERT INTO @Temp_Table
SELECT
@OutageDate AS OutageDate,
(DATEPART(HOUR, @Temp_StartTime)) AS StartHour,
@temp_EndMinute AS StartMinute,
@temp_StartHour+1 AS EndHour,
0 AS EndMinute,
@StartTime as StartTime,
@EndTime as EndTime,
@Duration AS Duration
--DATEADD returns a specified date with the specified number interval (signed integer) added to a specified datepart of that date.
SET @temp_StartHour=@temp_StartHour+1
SET @Temp_StartTime=DATEADD(HOUR,1,@Temp_StartTime)
--Let's make sure we account for the minutes in the first and last hours if any
if(DATEPART(MI, @Temp_StartTime)!=0)
BEGIN
SET @Temp_StartTime=DATEADD(MI,-@temp_StartMinute,@Temp_StartTime)
END
END
--Need to add logic that drops and recreates the table from the temp table so we don't have to employ a cursor
SELECT * FROM @Temp_Table
BEGIN
SELECT * INTO newTable FROM @Temp_Table
END
如果您在SMS中运行此直线,您将获得最基本的逻辑:
declare @StartTime time
declare @EndTime time
declare @Temp_StartTime time
declare @temp_StartHour int
declare @temp_EndHour int
declare @temp_StartMinute int
declare @temp_EndMinute int
SET @StartTime='2:30:00'
SET @EndTime='4:01:00'
SET @Temp_StartTime=@StartTime
SET @temp_StartHour=DATEPART(HOUR, @StartTime)
SET @temp_EndHour=DATEPART(HOUR, @EndTime)
SET @temp_StartMinute=DATEPART(MI, @StartTime)
SET @temp_EndMinute=DATEPART(MI, @EndTime)
if(@temp_EndMinute>0)
BEGIN
SET @temp_EndHour=@temp_EndHour+1
END
DECLARE @Temp_Table TABLE
(
StartHour int,
StartMinute int,
EndHour int,
EndMinute int,
StartTime time,
EndTime time
)
WHile((@temp_EndHour-@temp_StartHour>=1))
BEGIN
INSERT INTO @Temp_Table
SELECT (DATEPART(HOUR, @Temp_StartTime)) AS StartHour,(DATEPART(MINUTE, @Temp_StartTime)) AS StartMinute,
@temp_StartHour+1 AS EndHour,
0 AS EndMinute, @StartTime as StartTime, @EndTime as EndTime
SET @temp_StartHour=@temp_StartHour+1
SET @Temp_StartTime=DATEADD(HOUR,1,@Temp_StartTime)
if(DATEPART(MI, @Temp_StartTime)!=0)
BEGIN
SET @Temp_StartTime=DATEADD(MI,-@temp_StartMinute,@Temp_StartTime)
END
END
SELECT * FROM @Temp_Table
答案 0 :(得分:1)
首先,一些设置:
USE tempdb;
GO
CREATE TABLE dbo.Outages
(
OutageDate DATE,
StartTime TIME(7),
EndTime TIME(7),
Duration INT
);
INSERT dbo.Outages SELECT '20101110', '16:00', '17:30', 90;
/*
-- I also tested these cases, and *think* it still produces what you expect:
INSERT dbo.Outages SELECT '20101111', '13:00', '14:02', 62;
INSERT dbo.Outages SELECT '20101112', '17:00', '18:00', 60;
INSERT dbo.Outages SELECT '20101113', '16:05', '16:25', 20;
INSERT dbo.Outages SELECT '20101114', '16:59', '18:01', 62;
INSERT dbo.Outages SELECT '20101115', '22:15', '01:30', 165;
*/
现在,查询:
;WITH n(n) AS
(
SELECT TOP 24 ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.objects
),
x AS
(
SELECT
o.OutageDate, StartHour = (DATEPART(HOUR, StartTime) + n.n - 1) % 24,
StartTime, EndTime, Duration,
rn = ROW_NUMBER() OVER (PARTITION BY o.OutageDate, o.StartTime ORDER BY n.n)
FROM n INNER JOIN dbo.Outages AS o
ON n.n <= CEILING(DATEDIFF(MINUTE, CONVERT(DATETIME, StartTime),
DATEADD(DAY, CASE WHEN EndTime < StartTime THEN 1 ELSE 0 END,
CONVERT(DATETIME, EndTime)))/60.0)
),
mx AS (SELECT OutageDate, StartTime, minrn = MIN(rn), maxrn = MAX(rn)
FROM x GROUP BY OutageDate, StartTime)
-- insert into some other table
SELECT
x.OutageDate,
x.StartHour,
StartMinutes = CASE
WHEN x.rn = mx.minrn THEN DATEPART(MINUTE, x.StartTime) ELSE 0 END,
EndHour = x.StartHour + 1,
EndMinutes = CASE
WHEN x.rn = mx.maxrn THEN DATEPART(MINUTE, x.EndTime) ELSE 0 END,
x.StartTime,
x.EndTime,
x.Duration
FROM x INNER JOIN mx
ON x.OutageDate = mx.OutageDate
AND x.StartTime = mx.StartTime
ORDER BY x.OutageDate, x.rn;
GO
如果您对为各种方案提供正确的行感到高兴,那么请替换
-- insert into some other table
使用实际插入,例如
INSERT dbo.OtherTable(col1, col2, ...)
如果您尝试从此输出创建一个全新的表格,请替换
FROM x INNER JOIN mx
使用INTO子句,例如
INTO dbo.MyNewTable FROM x INNER JOIN mx
别忘了清理:
DROP TABLE dbo.Outages;