【发布时间】:2014-04-18 00:10:49
【问题描述】:
我使用的是 SQLServer 2008 R2
我正在尝试为特定时期(通常为 30-90 天)内制造资源的活动创建报告和图表
在运行期间(例如 4 天)创建作业。如果周末没有工作并且上述作业从星期五开始,则资源的活动需要显示运行 1 天、停运 2 天、运行 3 天,而生产调度程序不必使其成为两个作业。我在一张表中有工作的时间表,在另一张表中有停机时间(所以把 DT 想象成某种日历表)。不同寻常的是,结束时间会包含停机时间。
所以我需要查询来为这项工作创建 3 个日期时间范围:周五跑步、周六、太阳下山、周一、周二、周三跑步。注意:单个作业可以有多个停机事件。
在这个问题上兜圈子已经有一段时间了。我敢肯定有一种优雅的方法可以做到这一点:我就是找不到。我找到了几篇类似的帖子,但无法将任何内容应用于我的案例(或者至少无法让它们工作)
以下是一些示例日期和预期结果。我希望解释和示例数据清楚。
-- Create tables to work with / Source and Destination
CREATE TABLE #Jobs
(
ResourceID int
,JobNo VARCHAR(10)
,startdate SMALLDATETIME
,enddate SMALLDATETIME
)
CREATE TABLE #Downtime
(
ResourceID INT
,Reason VARCHAR(10)
,startdate SMALLDATETIME
,enddate SMALLDATETIME
)
CREATE TABLE #Results
(
ResourceID INT
,Activity VARCHAR(10)
,startdate SMALLDATETIME
,enddate SMALLDATETIME
,ActivityType varchar(1)
)
-- Job Schedule
INSERT INTO [#Jobs]
(
[ResourceID],
[JobNo],
startdate
,enddate
)
SELECT 1, 'J1', '2014-04-01 08:00' ,'2014-04-01 17:00'
UNION ALL
SELECT 1, 'J2', '2014-04-01 17:00' , '2014-04-01 23:00'
UNION ALL
SELECT 2, 'J3', '2014-04-01 08:00' ,'2014-04-01 23:00'
UNION ALL
SELECT 3, 'J4', '2014-04-01 08:00' ,'2014-04-01 09:00'
SELECT * FROM #jobs
-- Downtime Scehdule
INSERT INTO [#Downtime]
(
[ResourceID],
Reason,
startdate
,enddate
)
SELECT 1, 'DOWN', '2014-04-01 10:00' ,'2014-04-01 11:00'
UNION ALL
SELECT 1, 'DOWN', '2014-04-01 21:00' , '2014-04-01 22:00'
UNION ALL
SELECT 2, 'DOWN', '2014-04-01 10:00' ,'2014-04-01 11:00'
UNION ALL
SELECT 2, 'DOWN', '2014-04-01 21:00' , '2014-04-01 22:00'
UNION ALL
SELECT 3, 'DOWN', '2014-04-01 10:00' ,'2014-04-01 11:00'
UNION ALL
SELECT 3, 'DOWN', '2014-04-01 21:00' , '2014-04-01 22:00'
SELECT * FROM #Downtime
-- Expected Results
INSERT INTO [#Results]
(
Activity,
[ResourceID],
startdate
,enddate
,[ActivityType]
)
SELECT 'J1', 1, '2014-04-01 08:00' ,'2014-04-01 10:00', 'P'
UNION ALL
SELECT 'DOWN', 1, '2014-04-01 10:00' , '2014-04-01 11:00', 'D'
UNION ALL
SELECT 'J1', 1, '2014-04-01 11:00' ,'2014-04-01 17:00', 'P'
UNION ALL
SELECT 'J2', 1, '2014-04-01 17:00' , '2014-04-01 21:00', 'P'
UNION ALL
SELECT 'DOWN', 1, '2014-04-01 21:00' , '2014-04-01 22:00', 'D'
UNION ALL
SELECT 'J2', 1, '2014-04-01 22:00' ,'2014-04-01 23:00', 'P'
UNION ALL
SELECT 'J3', 2, '2014-04-01 08:00' ,'2014-04-01 10:00', 'P'
UNION ALL
SELECT 'DOWN', 2, '2014-04-01 10:00' , '2014-04-01 11:00', 'D'
UNION ALL
SELECT 'J3', 2, '2014-04-01 11:00' ,'2014-04-01 21:00', 'P'
UNION ALL
SELECT 'DOWN', 2, '2014-04-01 21:00' , '2014-04-01 22:00', 'D'
UNION ALL
SELECT 'J3', 2, '2014-04-01 22:00' ,'2014-04-01 23:00', 'P'
UNION ALL
SELECT 'J4', 3, '2014-04-01 08:00' ,'2014-04-01 09:00', 'P'
UNION ALL
SELECT 'DOWN', 3, '2014-04-01 10:00' , '2014-04-01 11:00', 'D'
UNION ALL
SELECT 'DOWN', 3, '2014-04-01 21:00' , '2014-04-01 22:00', 'D'
SELECT * FROM #Results
ORDER BY [ResourceID], Startdate
DELETE FROM #Results
|--------------------------J1---------- --------------|跑步
|----D1-----| |-------D2--------|向下
|--J1----|----D1-----|--------J1------|-------D2-------|- ----J1-----|结果
|-----------------------------J1------------|跑步
|----D1--------|向下
|-----------------J1----------------------| |----D1--------|结果
有人能指出正确的方向吗?
这是我最接近的。当有重叠时效果很好,但在 J4 上工作在停机前结束时失败
WITH cte
AS ( SELECT
ROW_NUMBER() OVER ( ORDER BY ResourceID, dt ) AS Rno
,x.ResourceID
,x.Activity
,Dt
,xdt.ActivityType
FROM
(
SELECT
ResourceID
,JobNo AS Activity
,startdate
,enddate
,'P' AS ActivityType
FROM #Jobs
UNION ALL
SELECT
ResourceID
,Reason AS Activity
,startdate
,enddate
,'D' AS ActivityType
FROM #Downtime
) AS x
CROSS APPLY
(
VALUES ( x.startdate, x.ActivityType),
( x.enddate, x.ActivityType) ) AS xdt
( Dt, ActivityType )
)
SELECT
x.ResourceID
,CASE WHEN x.Activity > x1.Activity THEN x.Activity
ELSE x1.Activity
END AS Activity
,x.dt AS StartDate
,x1.Dt AS EndDate
,CASE WHEN x.ActivityType > x1.ActivityType THEN x.ActivityType
ELSE x1.ActivityType
END AS activitytype
FROM
cte AS x
LEFT OUTER JOIN cte AS x1 ON x.ResourceID = x1.ResourceID
AND x.Rno = x1.Rno - 1
WHERE
x1.Dt IS NOT NULL
AND x1.Dt <> x.Dt;
谢谢
标记
【问题讨论】:
-
您的数据库是哪个平台和版本(尽管它可能是 SQL Server 发行版之一,是哪一个)?您提到日期,但您的数据仅在时间上有所不同,是什么?您是想将
INSERT数据转换为#Jobs和#Downtime,还是只是构建报告?日历表在这里将非常有用 - 你有一个,对吗?到目前为止,您尝试了哪些无效的方法?不过,感谢您很好地设置开始/结果数据。 (作为旁注,结束日期几乎总是派生信息,即其他状态开始的瞬间)。 -
@Clockwork-Muse 感谢您的回复。不敢相信我忘了提到平台。到目前为止,我已经尝试使用多个 CTE,将所有内容组合到一个表中 - 它们都没有接近,所以不认为值得发布
-
忘了说结束时间了。你是对的,通常你必须根据开始持续时间和停机时间来计算。但在这种情况下,结束时间是考虑到停机时间的。几乎就像它的历史数据一样:J1 在时间 A 开始并在时间 B 结束(包括停机时间)。停机时间分别记录
-
好吧,您尝试了哪些没有成功的方法,它是如何让您失败的?我仍然很困惑您是尝试为这两个表构建条目,还是只需要一个
SELECT语句(本质上是构建#Results)。 -
@Clockwork-Muse。我添加了我的最新结果和失败的详细信息。我有两个表(工作和停机时间)并尝试构建结果(即给定日期范围内 ResourceX 上的活动——结果在我上面的“图片”中)
标签: sql date datetime sql-server-2008-r2