Sql 在Oracle中连接并缩短一周中的天数
我有计时栏Sql 在Oracle中连接并缩短一周中的天数,sql,oracle,datetime,oracle11g,Sql,Oracle,Datetime,Oracle11g,我有计时栏 M 8:00 AM - 5:00 PM | Tu 8:00 AM - 5:00 PM | W 8:00 AM - 5:00 PM | Th 8:00 AM - 5:00 PM | F 8:00 AM - 5:00 PM 希望将其生成为 M-F 8:00 AM - 5:00 PM 有时,时间可能会随着时间的推移而改变 M 9:00 am - 9:00 pm | Tu 9:00 am - 9:00 pm | W 9:00 am - 9:00 pm | Th 9:00 am - 9:0
M 8:00 AM - 5:00 PM | Tu 8:00 AM - 5:00 PM | W 8:00 AM - 5:00 PM | Th 8:00 AM - 5:00 PM | F 8:00 AM - 5:00 PM
希望将其生成为
M-F 8:00 AM - 5:00 PM
有时,时间可能会随着时间的推移而改变
M 9:00 am - 9:00 pm | Tu 9:00 am - 9:00 pm | W 9:00 am - 9:00 pm | Th 9:00 am - 9:00 pm | F 9:00 am - 9:00 pm | Sa 9:00 am - 9:00 pm | Su 10:00 am - 6:00 pm
在这种情况下,我必须生成
M-Sa 9:00 am - 9:00 pm | Su 10:00 am - 6:00 pm
看一看这个循序渐进的例子。遵循代码中编写的注释 把它当作你可能会做的指南,因为如果在中间某个地方有不同的时间跨度(例如星期四),这种方法就不能正常工作。分组仍然可以,但以缩写形式命名的日期会有点错误,因为您会得到例如M-Su上午9:00-晚上9:00 | Th上午9:00-下午4:00。如果你不介意的话,很好
SQL> with
2 test (id, col) as
3 (
4 select 1, 'M 8:00 AM - 5:00 PM | Tu 8:00 AM - 5:00 PM | W 8:00 AM - 5:00 PM | Th 8:00 AM - 5:00 PM | F 8:00 AM - 5:00 PM' from dual union all
5 select 2, 'M 9:00 am - 9:00 pm | Tu 9:00 am - 9:00 pm | W 9:00 am - 9:00 pm | Th 9:00 am - 9:00 pm | F 9:00 am - 9:00 pm | Sa 9:00 am - 9:00 pm | Su 10:00 am - 6:00 pm' from dual
6 ),
7 temp as
8 -- split column to rows
9 (select id,
10 column_value rn,
11 trim(regexp_substr(upper(col), '[^|]+', 1, column_value)) val
12 from test join table(cast(multiset(select level from dual
13 connect by level <= regexp_count(col, '\|') + 1
14 ) as sys.odcinumberlist)) on 1 = 1
15 ),
16 extr as
17 -- extract day and time span into separate columns (for aggregating purposes)
18 (
19 select id,
20 rn,
21 substr(val, 1, instr(val, ' ')) c_day,
22 substr(val, instr(val, ' ') + 1) c_period
23 from temp
24 ),
25 agg1 as
26 (-- group values from the previous step
27 select id,
28 listagg(trim(c_day), ', ') within group (order by rn) days,
29 c_period
30 from extr
31 group by id, c_period
32 )
33 -- the final result
34 select id,
35 listagg
36 (initcap(regexp_substr(days, '^\w+') ||'-'|| regexp_substr(days, '\w+$')) || ' ' || lower(c_period), ' | ')
37 within group (order by id)
38 val
39 from agg1
40 group by id
41 order by id;
ID VAL
--- --------------------------------------------------
1 M-F 8:00 am - 5:00 pm
2 M-Sa 9:00 am - 9:00 pm | Su-Su 10:00 am - 6:00 pm
SQL>
或者,您可以命名共享相同时间跨度的所有天,而不是将其缩短那么多,这样无论哪几天的时间跨度不同,都会返回正确的结果。例如:
<... snip, as previous lines are not modified ...>
25 agg1 as
26 (-- group values from the previous step
27 select id,
28 listagg(trim(initcap(c_day)), ', ') within group (order by rn) ||' ' || upper(c_period) val
29 from extr
30 group by id, c_period
31 )
32 -- the final result
33 select id,
34 listagg (val, ' | ') within group (order by id) val
35 from agg1
36 group by id
37 order by id;
ID VAL
--- ----------------------------------------------------------------------------------------------------
1 M, Tu, W, Th, F 8:00 AM - 5:00 PM
2 M, Tu, W, F, Sa 9:00 AM - 9:00 PM | Su 10:00 AM - 6:00 PM | Th 9:00 AM - 4:00 PM
SQL>
谢谢,第二个很有帮助。