【问题标题】:Splitting time entries from one table, depending on other table根据另一个表从一个表中拆分时间条目
【发布时间】:2020-08-18 12:56:19
【问题描述】:

我有一个包含某些进程的开始和结束时间的表格,还有一个包含休息时间的开始和结束时间的表格。我想为每个进程生成一个包含单个条目的新视图,没有中断。我将尝试用一个例子来解释:

表一:

Process     |  START                |  STOP
Process xy  |  2020-08-18 08:00:00  |  2020-08-18 10:00:00

表二:

         |  pause_START          |  pause_STOP
Break 1  |  2020-08-18 08:20:00  |  2020-08-18 08:40:00
Break 2  |  2020-08-18 09:20:00  |  2020-08-18 09:40:00

期望的输出:

Process     |  START                |  STOP
Process xy  |  2020-08-18 08:00:00  |  2020-08-18 08:20:00
Process xy  |  2020-08-18 08:40:00  |  2020-08-18 09:20:00
Process xy  |  2020-08-18 09:40:00  |  2020-08-18 10:00:00

或视觉上:


如果每个条目使用选择和联合的组合最多有 一个 中断,我设法做到了,但如果每个进程有多个中断,这将不起作用。

首先我这样创建View1

SELECT        TOP (100) PERCENT dbo.Table1.Process, dbo.Table1.START, dbo.Table1.STOP
FROM            dbo.Table1 LEFT OUTER JOIN
                        dbo.Table2 ON dbo.Table1.START <= dbo.Table2.pause_START AND (dbo.Table1.STOP >= dbo.Table2.pause_START OR
                        dbo.Table1.STOP IS NULL) AND ((dbo.Table1.STOP >= dbo.Table2.pause_STOP OR
                        dbo.Table1.STOP IS NULL) AND dbo.Table1.START <= dbo.Table2.pause_STOP OR
                        dbo.Table2.pause_STOP IS NULL)
WHERE        (dbo.Table1.START > CAST(DATEADD(DAY, - 1, GETDATE()) AS DATE)) OR
                        (dbo.Table1.STOP IS NOT NULL)

然后我得到这样的间隔:

SELECT        dbo.View1.Process, dbo.View1.START AS 'start', View1_1.pause_START AS 'stop', dbo.View1.TAB, dbo.View1.MA_ID
FROM            dbo.View1 INNER JOIN
                       dbo.View1 AS View1_1 ON dbo.View1.Process = View1_1.Process AND dbo.View1.TAB = View1_1.TAB
WHERE        (View1_1.pause_START IS NOT NULL)
UNION
SELECT        dbo.View1.Process, dbo.View1.pause_STOP, View1_1.STOP, dbo.View1.TAB, dbo.View1.MA_ID
FROM            dbo.View1 INNER JOIN
                       dbo.View1 AS View1_1 ON dbo.View1.Process = View1_1.Process AND dbo.View1.TAB = View1_1.TAB
WHERE        (View1_1.pause_START IS NOT NULL)
UNION
SELECT        dbo.View1.Process, dbo.View1.START, View1_1.STOP, dbo.View1.TAB, dbo.View1.MA_ID
FROM            dbo.View1 INNER JOIN
                       dbo.View1 AS View1_1 ON dbo.View1.Process = View1_1.Process AND dbo.View1.TAB = View1_1.TAB
WHERE        (View1_1.pause_START IS NULL)

但正如我所提到的,这对于每个间隔的休息时间不超过一次。

任何帮助将不胜感激!

【问题讨论】:

  • 我有点困惑。第一个表是否有不止一行?中断是特定于进程的吗?
  • 嗨,戈登,是的,表 1 不止一行,这只是一个例子 :) 中断是特定于进程的(从没有中断的意义上说 outisde进程的

标签: sql sql-server datetime


【解决方案1】:

假设休息不重叠并且总是在开始和停止之间(如您的示例),然后使用 union all 组合不同的时间段:

-- first record
select t1.process, t1.start, min(t2.start) as end
from table1 t1 cross join
     table2 t2
group by t1.process, t1.start
union all
-- all the breaks
select t1.process, t2.start, t2.end
from table1 t1 cross join
     table2 t2
union all
-- all the in-between times
select process, starttime, endtime
from (select t1.process, t2.end as starttime, lead(t2.start) over (partition by t1.process order by t1.start) as endtime
      from table1 t1 cross join
           table2 t2
     ) t
where endtime is not null
union all
-- last record
select t1.process, max(t2.end), t1.end
from table1 t1 cross join
     table2 t2
group by t1.process, t1.start;

这应该适用于您问题中的数据。您的实际情况可能更复杂(重叠中断、table2 中每个进程的多行或其他)。如果是这样,请提出一个问题,并附上适当的样本数据、期望的结果和解释。

【讨论】:

  • 您的假设是正确的:中断不重叠,并且它们始终位于表 1 中的一个进程的启动和停止之间。在代码之后,尽管您在 @987654324 中编写了“每个进程的多行” @",这正是我想要解决的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 2021-04-06
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
相关资源
最近更新 更多