簡體   English   中英

我如何將工作時間轉換為布爾值?

[英]how do i convert the working hours to Boolean?

我如何轉換工作時間 08:00:00-11:59:00;13:00:00-16:59:00; 成 48 位布爾格式,如

 "000000000000000011111111001111111100000000000000" 

其中每個數字是指使用 Oracle SQL 查詢的 30 分鍾粒度?

假設您從一個字符串開始,該字符串始終具有以分號分隔的 from/to 時間對,最后一對后面有一個尾隨分號; 這些時間總是 HH24:MI:SS,如圖所示,秒總是零; 然后...您可以將字符串拆分為多個字符串對,代表每個從/到對:

select regexp_substr('08:00:00-11:59:00;13:00:00-16:59:00;', '(.*?)(;|-|$)', 1, (2 * level - 1), null, 1),
  regexp_substr('08:00:00-11:59:00;13:00:00-16:59:00;', '(.*?)(;|-|$)', 1, 2 * level, null, 1)
from dual
connect by level <= regexp_count('08:00:00-11:59:00;13:00:00-16:59:00;', ';')
REGEXP_S REGEXP_S
-------- --------
08:00:00 11:59:00
13:00:00 16:59:00

您可以在一個正常的一天內生成所有半小時的塊(選擇一個不受 DST 切換影響的塊):

select to_char(date '2000-01-01' + ((level - 1) / 48), 'HH24:MI":00"')
from dual
connect by level <= 48
TO_CHAR(
--------
00:00:00
00:30:00
01:00:00
01:30:00
02:00:00
...
23:00:00
23:30:00

然后使用字符串比較將它們連接在一起以查看重疊的地方(這就是時間格式很重要的原因); 為簡單起見,使用 CTE 提供初始字符串,然后提供前兩個查詢的結果:

with t1 (working_hours) as (
  select '08:00:00-11:59:00;13:00:00-16:59:00;' from dual
),
t2 (working_from, working_to) as (
  select regexp_substr(working_hours, '(.*?)(;|-|$)', 1, (2 * level - 1), null, 1),
    regexp_substr(working_hours, '(.*?)(;|-|$)', 1, 2 * level, null, 1)
  from t1
  connect by level <= regexp_count(working_hours, ';')
),
t3 (block_from) as (
  select to_char(date '2000-01-01' + ((level - 1) / 48), 'HH24:MI":00"')
  from dual
  connect by level <= 48
)
select block_from,
  case when t2.working_from is null then 0 else 1 end as flag
from t3
left join t2 on t2.working_from <= t3.block_from and t2.working_to >= t3.block_from
BLOCK_FROM  FLAG
----------  ----
00:00:00    0
00:30:00    0
...
07:30:00    0
08:00:00    1
08:30:00    1
...
11:00:00    1
11:30:00    1
12:00:00    0
12:30:00    0
13:00:00    1
13:30:00    1
...
16:00:00    1
16:30:00    1
17:00:00    0
...
23:00:00    0
23:30:00    0

然后最后將它們聚合成一個結果字符串:

with t1 (working_hours) as (
  select '08:00:00-11:59:00;13:00:00-16:59:00;' from dual
),
t2 (working_from, working_to) as (
  select regexp_substr(working_hours, '(.*?)(;|-|$)', 1, (2 * level - 1), null, 1),
    regexp_substr(working_hours, '(.*?)(;|-|$)', 1, 2 * level, null, 1)
  from t1
  connect by level <= regexp_count(working_hours, ';')
),
t3 (block_from) as (
  select to_char(date '2000-01-01' + ((level - 1) / 48), 'HH24:MI":00"')
  from dual
  connect by level <= 48
)
select listagg(case when t2.working_from is null then 0 else 1 end)
  within group (order by t3.block_from) as result
from t3
left join t2 on t2.working_from <= t3.block_from and t2.working_to >= t3.block_from
RESULT
------------------------------------------------
000000000000000011111111001111111100000000000000

數據庫<>小提琴

如果您的初始字符串實際上來自一個表,並且您需要一次對多行進行此轉換,則連接拆分會稍微復雜一些,並且遞歸 CTE 可能更適合該部分。

只是為了好玩, 這里有一個例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM