Reputation: 633
I am working on a sql oracle database. I have a table with an id, begindate and enddate.
For example:
employee | begindate | enddate
john | 18/02/2015 | 18/02/2015
john | 19/02/2015 | 21/02/2015
I want to do a select statement of that table, but when the begindate is not equal to the enddate, it have to add some rows. In the example above the first line will stay like that, but the second line has to be expanded in three rows. the result of the select statement has to be:
john | 18/02/2015 | 18/02/2015
john | 19/02/2015 | 19/02/2015
john | 20/02/2015 | 20/02/2015
john | 21/02/2015 | 21/02/2015
So my select statement would have in this example 4 rows in total.
Has someone an idea how I can do that?
Upvotes: 0
Views: 264
Reputation: 23588
Here's an alternative answer using connect by directly on the table:
with test as (select 'john' employee, to_date('18/02/2015', 'dd/mm/yyyy') begindate, to_date('18/02/2015', 'dd/mm/yyyy') enddate from dual union all
select 'john' employee, to_date('19/02/2015', 'dd/mm/yyyy') begindate, to_date('21/02/2015', 'dd/mm/yyyy') enddate from dual)
select employee,
begindate + level - 1 begindate,
begindate + level - 1 enddate
from test
connect by prior employee = employee
and prior begindate = begindate
and prior sys_guid() is not null
and begindate + level - 1 <= enddate;
EMPLOYEE BEGINDATE ENDDATE
-------- ---------- ----------
john 18/02/2015 18/02/2015
john 19/02/2015 19/02/2015
john 20/02/2015 20/02/2015
john 21/02/2015 21/02/2015
I would recommend you test the answers which work and see which one has the best performance for your data.
Upvotes: 1
Reputation: 3586
The solution would be very similar to ORACLE SQL:Get all integers between two numbers with "two numbers" being the date span between begindate
and enddate
.
Something like:
Create Table test (employee varchar(50), begindate date, enddate date);
Insert Into test (employee, begindate, enddate)
Values ('john', TO_DATE('18/02/2015', 'dd/mm/yyyy'), TO_DATE('18/02/2015', 'dd/mm/yyyy'));
Insert Into test (employee, begindate, enddate)
Values ('john', TO_DATE('19/02/2015', 'dd/mm/yyyy'), TO_DATE('21/02/2015', 'dd/mm/yyyy'));
And then
Select employee, enumdate As begindate, enumdate As enddate
From test Cross Apply (
Select begindate + rownum - 1 As enumdate
From Dual
Connect By Level <= enddate - begindate + 1
) enum;
Upvotes: 0
Reputation: 168061
Oracle Setup:
CREATE TABLE employees ( employee, begindate, enddate ) AS
SELECT 'john', DATE '2015-02-18', DATE '2015-02-18' FROM DUAL UNION ALL
SELECT 'john', DATE '2015-02-19', DATE '2015-02-21' FROM DUAL;
Query:
SELECT e.employee,
t.COLUMN_VALUE AS begindate,
t.COLUMN_VALUE AS enddate
FROM employees e,
TABLE(
CAST(
MULTISET(
SELECT e.begindate + LEVEL - 1
FROM DUAL
CONNECT BY LEVEL <= e.enddate - e.begindate + 1
)
AS SYS.ODCIDATELIST
)
) t;
Results:
EMPLOYEE BEGINDATE ENDDATE
-------- --------- ---------
john 18-FEB-15 18-FEB-15
john 19-FEB-15 19-FEB-15
john 20-FEB-15 20-FEB-15
john 21-FEB-15 21-FEB-15
Upvotes: 3