简体   繁体   English

如何从 SQL 的一组时间范围中删除特定的时间范围?

[英]How to remove specific time ranges, from a set of time ranges in SQL?

With this example set of timestamp ranges:使用此示例时间戳范围集:

WITH sessions AS (
  (
  SELECT 
    TIMESTAMP('2022-09-24 13:49:32+0100') AS start,
    TIMESTAMP('2022-09-26 02:06:17+0100') AS end
  
  UNION ALL
  
  SELECT
    TIMESTAMP('2022-09-26 08:42:19+0100'), 
    TIMESTAMP('2022-09-26 09:41:40+0100'),  

  UNION ALL
 
  SELECT
    TIMESTAMP('2022-09-26 09:53:06+0100'),
    TIMESTAMP('2022-09-26 11:20:34+0100'))
)

SELECT * FROM sessions WHERE.... 

How would I go about removing all time between Fridays 17:00, America/New_York and Monday 09:00 Asia/Shanghai?我 go 如何删除美国/纽约周五 17:00 和亚洲/上海周一 09:00 之间的所有时间?

I really can't seem to figure this out.我似乎真的想不通。

"Best" thing I can think of is generating a table with all Friday/Monday ranges, and joining against that table, using the standard Gaps and Islands solution, is that really the best way?我能想到的“最好”的事情是生成一个包含所有周五/周一范围的表格,并使用标准的 Gaps and Islands 解决方案加入该表格,这真的是最好的方法吗?

Thanks!谢谢!

Edit:编辑:

The context is wait and resolution times for a ticketing system, where only time within the open operating hours should count.上下文是票务系统的等待和解决时间,其中只计算开放营业时间内的时间。 The service is staffed by various international teams, so the services operating hours become more complicated.该服务由各种国际团队组成,因此服务的运营时间变得更加复杂。

I would expect the results to look like this:我希望结果看起来像这样:

Start                     End                       Status
2022-09-24 13:49:32+0100  2022-09-26 02:00:00+0100  Closed
2022-09-26 02:00:00+0100  2022-09-26 02:06:17+0100  Open
2022-09-26 08:42:19+0100  2022-09-26 09:41:40+0100  Open
2022-09-26 09:53:06+0100  2022-09-26 11:20:34+0100  Open

Because the part of the 26th is within the working hours of Shanghai.因为26号这部分是在上海的工作时间内。

Assuming Monday 09:00 Asia/Shanghai corresponds to Sunday 21:00 America/New_York I came up with the following (I only filtered by the column start , if necessary you can apply the same to end ):假设周一 09:00 Asia/Shanghai 对应于周日 21:00 America/New_York 我想出了以下内容(我只按start列过滤,如有必要,您可以将其应用于end ):

WITH sessions AS (
  (
  SELECT TIMESTAMP('2022-09-24T13:49:32+0100') AS `start`, TIMESTAMP('2022-09-26T02:06:17+0100') AS `end` UNION ALL
  SELECT TIMESTAMP('2022-09-26T08:42:19+0100'), TIMESTAMP('2022-09-26T09:41:40+0100'),  UNION ALL
  SELECT TIMESTAMP('2022-09-26T09:53:06+0100'), TIMESTAMP('2022-09-26T11:20:34+0100')) 
)

SELECT *
FROM sessions 
WHERE 
  NOT (
    (EXTRACT(DAYOFWEEK FROM start AT TIME ZONE 'America/New_York') = 6 AND EXTRACT(TIME FROM start AT TIME ZONE 'America/New_York') > TIME(17, 0, 0))
    OR 
    (EXTRACT(DAYOFWEEK FROM start AT TIME ZONE 'America/New_York') = 7)
    OR 
    (EXTRACT(DAYOFWEEK FROM start AT TIME ZONE 'America/New_York') = 1 AND EXTRACT(TIME FROM start AT TIME ZONE 'America/New_York') < TIME(21, 0, 0))
  )

Short explanation:简短说明:
DAYOFWEEK gives you the weekday, Sundays being 1 ( see docs ). DAYOFWEEK为您提供工作日,星期日为1请参阅文档)。 For Friday and Sunday I also compare the times with the thresholds and exclude them from the results, Saturday I exclude completely.对于周五和周日,我还将时间与阈值进行比较并将它们从结果中排除,周六我完全排除。

Edit after comments:评论后编辑:

The following will exclude all periods that fall in the closed time.以下将排除所有属于关闭时间的时段。 Periods that overlap with the closed time are truncated.与关闭时间重叠的时段将被截断。 Only periods in open time are returned.仅返回开放时间段。 Added a few comments for explaining the query:添加了一些注释来解释查询:

-- Assuming closed period in UTC is from Friday 22:00 to Monday 01:00
-- Assuming start and end do not span over the closed period

WITH sessions AS (
  (
  SELECT TIMESTAMP('2022-09-24T13:49:32+0100') AS `start`, TIMESTAMP('2022-09-26T02:06:17+0100') AS `end` UNION ALL
  SELECT TIMESTAMP('2022-09-26T08:42:19+0100'), TIMESTAMP('2022-09-26T09:41:40+0100'),  UNION ALL
  SELECT TIMESTAMP('2022-09-23T08:42:19+0100'), TIMESTAMP('2022-09-25T09:41:40+0100'),  UNION ALL
  SELECT TIMESTAMP('2022-09-26T09:53:06+0100'), TIMESTAMP('2022-09-26T11:20:34+0100')) 
)

SELECT 
CASE 
  WHEN start_offset IS NOT NULL THEN TIMESTAMP_ADD(TIMESTAMP(DATETIME(EXTRACT(YEAR FROM start), EXTRACT(MONTH FROM start), EXTRACT(DAY FROM start), 1, 0, 0)), INTERVAL start_offset DAY) 
  ELSE start
  END as new_start, -- using the determined offset, time is fixed
CASE 
  WHEN end_offset IS NOT NULL THEN TIMESTAMP_SUB(TIMESTAMP(DATETIME(EXTRACT(YEAR FROM `end`), EXTRACT(MONTH FROM `end`), EXTRACT(DAY FROM `end`), 22, 0, 0)), INTERVAL end_offset DAY)
  ELSE `end`
  END as new_end, -- using the determined offset, time is fixed
FROM
(
  SELECT 
  *,
  CASE 
    WHEN (EXTRACT(DAYOFWEEK FROM start) = 6 AND EXTRACT(TIME FROM start) > TIME(22, 0, 0)) THEN 3
    WHEN (EXTRACT(DAYOFWEEK FROM start) = 7) THEN 2
    WHEN (EXTRACT(DAYOFWEEK FROM start) = 1) THEN 1
    WHEN (EXTRACT(DAYOFWEEK FROM start) = 2 AND EXTRACT(TIME FROM start) < TIME(1, 0, 0)) THEN 0
    ELSE NULL
    END AS start_offset, -- determine how many days to offset the start (adding to start date)
  CASE 
    WHEN (EXTRACT(DAYOFWEEK FROM `end`) = 6 AND EXTRACT(TIME FROM `end`) > TIME(22, 0, 0)) THEN 0
    WHEN (EXTRACT(DAYOFWEEK FROM `end`) = 7) THEN 1
    WHEN (EXTRACT(DAYOFWEEK FROM `end`) = 1) THEN 2
    WHEN (EXTRACT(DAYOFWEEK FROM `end`) = 2 AND EXTRACT(TIME FROM `end`) < TIME(1, 0, 0)) THEN 3
    ELSE NULL
    END AS end_offset, -- determine how many days to offset the end (subtracting from end date)
  FROM sessions
)
WHERE NOT (start_offset IS NOT NULL AND end_offset IS NOT NULL)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 获取相同时间范围对应的行 - Get rows corresponding to the same time ranges 如何允许从某些 ip 范围到 aks 外部负载均衡器的流量 - How to allow trafic from some ip ranges to aks external loadbalancer 在 Flutter 中,如果我们在 firestore 中有日期参数,我们如何使用 firebase 获取特定日期范围之间的数据? - In Flutter how can we able to get the data between specific date ranges using firebase if we had date parameter in firestore? SQL 查询:select后面的所有行每次特定参数获取特定值 - SQL query: How to select all following rows every time specific parameter acquires specific value 如何从 SQL 中的时间戳获取周开始日期 - How to get week start date from time stamp in SQL 如何在AWS的特定时间触发Lambda function? - How to trigger a Lambda function at specific time in AWS? 如何在 BigQuery 中获取特定时间段的数据 - How to fetch data for a specific time period in BigQuery 在 GCP 中,如何创建防火墙规则以按 IP 范围隔离子网? - In GCP, how to create firewall rules to isolate subnets by their IP ranges? 如何使用 Cosmos 更改提要(推送)并行处理不同的分区范围? - How to parallel process different partition ranges with Cosmos change feed (push)? 如何在 ARM 模板中放置多个目标端口范围? - How to put multiple destination port ranges in ARM templates?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM