我正在开发一个项目,该项目需要能够在非标准用户定义的时间间隔内动态分组源数据的报表,例如指定开始和结束范围内的生产班次。示例用户可能希望在过去两天按班次查看生产信息组。 我创建了一个名为“IntervalConfiguration”的表,它存储了使用以下数据创建分组间隔所需的配置信息:
IntervalType SubIntervalType IntervalDuration IntervalDurationUnits IntervalStartReferenceTime IntervalRepeatDuration IntervalRepeatDurationUnits
------------------------- ------------------- -------------------- --------------------- -------------------------- ---------------------- ---------------------------
Production Day ProductionDay 1 Days 2013-01-07 07:00:00.000 1 Days
Production Month ProductionMonth 1 Months 2013-01-01 07:00:00.000 1 Months
Production Week ProductionWeek 1 Weeks 2013-01-07 08:45:00.000 1 Weeks
Production Year ProductionYear 1 Years 2013-01-01 08:45:00.000 1 Years
Site A - Production Shift Day 12 Hours 2013-01-06 07:00:00.000 24 Hours
Site A - Production Shift Night 12 Hours 2013-01-06 19:00:00.000 24 Hours
Site B - Production Shift Day 12 Hours 2013-01-06 06:45:00.000 24 Hours
Site B - Production Shift Night 12 Hours 2013-01-06 18:45:00.000 24 Hours
如果用户选择“站点A - 生产班次”作为报告的分组间隔,开始日期为“01/01/2018”,结束日期为“01/05/2018”,则报告必须创建日班的分组间隔,其中日班时间从早上7点开始,到晚上7点结束,夜间班次从晚上7点开始,到第二天早上7点结束。 此外,只应返回完全包含在开始日期和结束日期内的分组间隔。下面是所描述方案的预期分组间隔的示例。
SubIntervalType IntervalStart IntervalEnd
---------------- ----------------------- -----------------------
Day 2018-01-01 07:00:00.000 2018-01-01 19:00:00.000
Night 2018-01-01 19:00:00.000 2018-01-02 07:00:00.000
Day 2018-01-02 07:00:00.000 2018-01-02 19:00:00.000
Night 2018-01-02 19:00:00.000 2018-01-03 07:00:00.000
Day 2018-01-03 07:00:00.000 2018-01-03 19:00:00.000
Night 2018-01-03 19:00:00.000 2018-01-04 07:00:00.000
Day 2018-01-04 07:00:00.000 2018-01-04 19:00:00.000
如果用户选择生产月作为分组间隔,开始日期为'01 / 01/2018'且结束日期为'01 / 01/2011',则报告应生成以下分组间隔。
SubIntervalType IntervalStart IntervalEnd
----------------- ----------------------- -----------------------
ProductionMonth 2018-01-01 07:00:00.000 2018-02-01 07:00:00.000
ProductionMonth 2018-02-01 07:00:00.000 2018-03-01 07:00:00.000
ProductionMonth 2018-03-01 07:00:00.000 2018-04-01 07:00:00.000
ProductionMonth 2018-04-01 07:00:00.000 2018-05-01 07:00:00.000
ProductionMonth 2018-05-01 07:00:00.000 2018-06-01 07:00:00.000
ProductionMonth 2018-06-01 07:00:00.000 2018-07-01 07:00:00.000
ProductionMonth 2018-07-01 07:00:00.000 2018-08-01 07:00:00.000
ProductionMonth 2018-08-01 07:00:00.000 2018-09-01 07:00:00.000
ProductionMonth 2018-09-01 07:00:00.000 2018-10-01 07:00:00.000
ProductionMonth 2018-10-01 07:00:00.000 2018-11-01 07:00:00.000
ProductionMonth 2018-11-01 07:00:00.000 2018-12-01 07:00:00.000
我已经开始构建下面的表值函数来动态创建所需的分组间隔。
CREATE FUNCTION [dbo].[GetIntervals]
(
@dateRangeStart datetime,
@dateRangeEnd datetime,
@groupByInterval NVARCHAR(200)
)
RETURNS @Intervals TABLE (
IntervalType NVARCHAR(100)
,SubIntervalType NVARCHAR(100)
,IntervalStart DATETIME
,IntervalEnd DATETIME
,IntervalDurationSeconds FLOAT
)
AS
BEGIN
DECLARE @activeIntervalDateTime DATETIME = DATEADD(millisecond, 3, @dateRangeStart);
DECLARE @intervalStartTime DATETIME = DATEADD(s, 1, @dateRangeStart);
DECLARE @intervalEndTime DATETIME = DATEADD(s, 1, @dateRangeStart);
DECLARE @intervalDurationSeconds FLOAT;
DECLARE @intervalName NVARCHAR(100);
DECLARE @subIntervalType NVARCHAR(100);
WHILE @intervalStartTime <= @dateRangeEnd
BEGIN
SELECT TOP 1
@intervalName = IntervalType ,@subIntervalType = SubIntervalType , @intervalStartTime = IntervalStart, @intervalEndTime = IntervalEnd
FROM (SELECT IntervalType, SubIntervalType, IntervalDuration, IntervalDurationUnits,
IntervalRepeatDuration, IntervalRepeatDurationUnits,
CASE IntervalRepeatDurationUnits
WHEN 'Hours' THEN (DateAdd(HH, (DateDiff(HH, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime))
WHEN 'Days' THEN (DateAdd(D, (DateDiff(D, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime))
WHEN 'Months'THEN (DateAdd(MM, (DateDiff(MM, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime))
END AS IntervalStart,
CASE IntervalRepeatDurationUnits
WHEN 'Hours' THEN (DateAdd(HH, IntervalDuration, DateAdd(HH, (DateDiff(HH, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime)))
WHEN 'Days' THEN
CASE IntervalDurationUnits
WHEN 'Hours' THEN (DateAdd(HH, IntervalDuration, DateAdd(D, (DateDiff(D, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime)))
WHEN 'Days' THEN (DateAdd(D, IntervalDuration, DateAdd(D, (DateDiff(D, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime)))
END
WHEN 'Months'THEN
CASE IntervalDurationUnits
WHEN 'Hours' THEN (DateAdd(HH, IntervalDuration, DateAdd(MM, (DateDiff(MM, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime)))
WHEN 'Days' THEN (DateAdd(D, IntervalDuration, DateAdd(MM, (DateDiff(MM, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime)))
WHEN 'Months' THEN (DateAdd(MM, IntervalDuration, DateAdd(MM, (DateDiff(MM, IntervalStartReferenceTime, ActiveTimeNormalized ) / IntervalRepeatDuration) * IntervalRepeatDuration, IntervalStartReferenceTime)))
END
END AS IntervalEnd
,IntervalStartReferenceTime
FROM (
SELECT IntervalType, SubIntervalType, IntervalDuration, IntervalDurationUnits, IntervalRepeatDuration, IntervalRepeatDurationUnits, IntervalStartReferenceTime,
CASE IntervalRepeatDurationUnits
WHEN 'Hours' THEN DATEADD(MILLISECOND, -1*(DATEPART(MILLISECOND, IntervalStartReferenceTime) + 3), DATEADD(SECOND, -1*DATEPART(SECOND, IntervalStartReferenceTime), DATEADD(MINUTE, -1*DATEPART(MINUTE, IntervalStartReferenceTime), @activeIntervalDateTime)))
WHEN 'Days' THEN DATEADD(MILLISECOND, -1*(DATEPART(MILLISECOND, IntervalStartReferenceTime) + 3), DATEADD(SECOND, -1*DATEPART(SECOND, IntervalStartReferenceTime), DATEADD(MINUTE, -1*DATEPART(MINUTE, IntervalStartReferenceTime), DATEADD(HOUR, -1*DATEPART(HOUR, IntervalStartReferenceTime), @activeIntervalDateTime))))
WHEN 'Months' THEN DATEADD(MILLISECOND, -1*(DATEPART(MILLISECOND, IntervalStartReferenceTime) + 3), DATEADD(SECOND, -1*DATEPART(SECOND, IntervalStartReferenceTime), DATEADD(MINUTE, -1*DATEPART(MINUTE, IntervalStartReferenceTime), DATEADD(HOUR, -1*DATEPART(HOUR, IntervalStartReferenceTime), DATEADD(DAY, -1*(DATEPART(DAY, IntervalStartReferenceTime) - 1), @activeIntervalDateTime)))))
END AS ActiveTimeNormalized
FROM dbo.IntervalConfiguration
) norm
WHERE IntervalType = @groupByInterval) interval
WHERE (@activeIntervalDateTime > IntervalStart) and (@activeIntervalDateTime <= IntervalEnd)
ORDER BY IntervalStartReferenceTime DESC
SET @intervalDurationSeconds = DATEDIFF(SECOND, @intervalStartTime, @intervalEndTime);
IF @intervalStartTime >= @dateRangeStart AND @intervalEndTime <= @dateRangeEnd
BEGIN
INSERT INTO @Intervals(
IntervalType
,SubIntervalType
,IntervalStart
,IntervalEnd
,IntervalDurationSeconds
)
VALUES(
@intervalName
,@subIntervalType
,@intervalStartTime
,@intervalEndTime
,@intervalDurationSeconds
)
END
SET @activeIntervalDateTime = DATEADD(MILLISECOND, 3, @intervalEndTime);
END
RETURN;
END
然而,这个功能变得越来越复杂,难以调试我也想消除在函数中使用While循环的需要。我的问题是,是否有更简单的方法来实现我的要求,是否可以消除对while循环的需求?
答案 0 :(得分:0)
您可以通过使用计数表来简化查询并消除while循环,如下所示:
<UITabBarController>,
| <UINavigationController>
| | <HomeViewController>
| <UINavigationController>
| | <ChatViewController>
| <UINavigationController>
| | <ProfileViewController>