展开行中的日期范围 - Oracle SQL
Expand Range of dates in rows - Oracle SQL
我的记录显示一名员工从 2021 年 3 月 23 日到 2021 年 3 月 26 日休了年假,即如下所示的 3 天。
我正在尝试将记录拆分为三个开始日期和结束日期以获得单独的记录。例如:
这样做的主要原因是总结组织在一个月内休假的总数。
这可能吗?尝试了一些不同的东西,但没有成功。
这是一种选择;阅读代码中的注释。
SQL> with
2 -- sample data
3 data (id, start_date, end_date, att_type, descr, abs_days, abs_hours) as
4 (select 1, date '2021-04-23', date '2021-04-26', 3000, 'ANN', 3, 29 from dual),
5 -- calculate number of days when person identified by ID has been absent
6 temp (id, diff) as
7 (select id, end_date - start_date
8 from data
9 )
10 -- hierarchical query, to create as many rows as there are days. Cross join is here
11 -- to avoid duplicates when you run that query for more than a single person
12 select
13 d.id,
14 d.start_date + column_value - 1 start_date,
15 d.start_date + column_value end_date,
16 d.att_type,
17 d.descr,
18 d.abs_days / t.diff abs_days,
19 round(d.abs_hours / t.diff, 2) abs_hours
20 from data d join temp t on t.id = d.id
21 cross join table(cast(multiset(select level from dual
22 connect by level <= t.diff
23 ) as sys.odcinumberlist))
24 order by d.id, d.start_date;
ID START_DATE END_DATE ATT_TYPE DES ABS_DAYS ABS_HOURS
---------- ---------- ---------- ---------- --- ---------- ----------
1 23/04/2021 24/04/2021 3000 ANN 1 9,67
1 24/04/2021 25/04/2021 3000 ANN 1 9,67
1 25/04/2021 26/04/2021 3000 ANN 1 9,67
SQL>
在我看来,ABS_HOURS
您在示例数据中发布的内容是错误的。工作日有多少小时(在这里,我住的地方,每天 8 小时),这就是每 3 天正好 24 小时。如果您居住的地方不同,没问题 - 可能是 9 小时或 10 小时,但这个数字(或者至少 应该 )每天都一样。因此,每 3 天 29 小时在我看来是错误的。
这反映了最终查询中的 ABS_HOURS
。您希望 9.6 + 9.6 + 9.7 等于 29 小时。这并不容易(至少对我来说不是)所以在这种情况下我会切换到 PL/SQL。
我的记录显示一名员工从 2021 年 3 月 23 日到 2021 年 3 月 26 日休了年假,即如下所示的 3 天。
我正在尝试将记录拆分为三个开始日期和结束日期以获得单独的记录。例如:
这样做的主要原因是总结组织在一个月内休假的总数。
这可能吗?尝试了一些不同的东西,但没有成功。
这是一种选择;阅读代码中的注释。
SQL> with
2 -- sample data
3 data (id, start_date, end_date, att_type, descr, abs_days, abs_hours) as
4 (select 1, date '2021-04-23', date '2021-04-26', 3000, 'ANN', 3, 29 from dual),
5 -- calculate number of days when person identified by ID has been absent
6 temp (id, diff) as
7 (select id, end_date - start_date
8 from data
9 )
10 -- hierarchical query, to create as many rows as there are days. Cross join is here
11 -- to avoid duplicates when you run that query for more than a single person
12 select
13 d.id,
14 d.start_date + column_value - 1 start_date,
15 d.start_date + column_value end_date,
16 d.att_type,
17 d.descr,
18 d.abs_days / t.diff abs_days,
19 round(d.abs_hours / t.diff, 2) abs_hours
20 from data d join temp t on t.id = d.id
21 cross join table(cast(multiset(select level from dual
22 connect by level <= t.diff
23 ) as sys.odcinumberlist))
24 order by d.id, d.start_date;
ID START_DATE END_DATE ATT_TYPE DES ABS_DAYS ABS_HOURS
---------- ---------- ---------- ---------- --- ---------- ----------
1 23/04/2021 24/04/2021 3000 ANN 1 9,67
1 24/04/2021 25/04/2021 3000 ANN 1 9,67
1 25/04/2021 26/04/2021 3000 ANN 1 9,67
SQL>
在我看来,ABS_HOURS
您在示例数据中发布的内容是错误的。工作日有多少小时(在这里,我住的地方,每天 8 小时),这就是每 3 天正好 24 小时。如果您居住的地方不同,没问题 - 可能是 9 小时或 10 小时,但这个数字(或者至少 应该 )每天都一样。因此,每 3 天 29 小时在我看来是错误的。
这反映了最终查询中的 ABS_HOURS
。您希望 9.6 + 9.6 + 9.7 等于 29 小时。这并不容易(至少对我来说不是)所以在这种情况下我会切换到 PL/SQL。