我在一个组织工作,在这个组织中,用户有时会按照“分割”的时间表工作,数据的结构如下所示:
| 使用者|开始时间|结束时间|类型|
| --------------|--------------|--------------|--------------|
| 用户1|23年3月29日上午8:00|23年3月29日8:00 PM|打开|
| 用户1|23年3月29日12:00 PM|23年3月29日下午4:00|已关闭|
| 用户2|2023年3月29日上午10:00|23年3月29日10:00 PM|打开|
| 用户2|23年3月29日下午2:00|23年3月29日下午6:00|已关闭|
问题是,我需要知道他们的工作时间,而不是他们的“关闭”时间-我如何使它这样的最终结果看起来像这样:
| 使用者|开始时间|结束时间|
| --------------|--------------|--------------|
| 用户1|23年3月29日上午8:00|23年3月29日12:00 PM|
| 用户1|23年3月29日下午4:00|23年3月29日8:00 PM|
| 用户2|2023年3月29日上午10:00|23年3月29日下午2:00|
| 用户2|23年3月29日下午6:00|23年3月29日10:00 PM|
我试过使用PARTITION BY,但出于对我的爱,无法得到我想要的结果......可能是我做错了
4条答案
按热度按时间yks3o0rb1#
这是可以使用的查询。
它依赖于相当沉重的假设:
此查询合并了三个部分:
1.只开放班次
1.移位的第一部分(从打开部分的开始到关闭部分的开始)
1.移位的第二部分(从闭合部分结束到打开部分结束)
0pizxfdo2#
您可以
UNPIVOT
时间,然后使用分析函数来计算开放和封闭的开始时间是否多于结束时间,并过滤仅具有开放范围的一部分而不是封闭范围的一部分的那些范围。(Note:这将处理:开放范围内的多个封闭范围;相同类型的重叠范围;跨越天的范围;以及没有包含开放范围的封闭范围)。
其中,对于示例数据:
输出:
| 用户名|时间_开始|时间结束|
| --------------|--------------|--------------|
| 用户1|2023年3月29日08时00分|2023年3月29日12时00分|
| 用户1|2023-03-29 16:00:00|2023-03-29 20:00:00|
| 用户2|2023-03-29 10:00:00|2023-03-29 14:00:00|
| 用户2|2023-03-29 18:00:00|2023-03-29 22:00:00|
| 用户3|2023-03-29 10:00:00|2023-03-29 11:00:00|
| 用户3|2023年3月29日12时00分|2023年3月29日13时00分|
| 用户3|2023-03-29 14:00:00|2023-03-29 22:00:00|
fiddle
w80xi6nr3#
您可以使用下面的解决方案来解决您的问题。它使用解析函数LAG和LEAD来实现所需的逻辑。我假设您在开放范围内没有多个封闭范围。
demo
kh212irz4#
也许你想在一行中有一个用户的班次和休息时间。这可以使用分析函数LEAD()和LAG()与Case表达式的组合来完成。代码根据下面的示例数据进行了调整,并且限制在一个工作日中最多两次休息(应该足够了)
如果你想要just working hours-你所要做的就是在主SQL的Select列表中只选择它们: