在不同的行中展开一行

时间:2016-01-12 13:16:32

标签: sql oracle

我正在开发一个sql oracle数据库。我有一张带有id,begindate和enddate的表。

例如:

employee | begindate  |  enddate
john     | 18/02/2015 |  18/02/2015
john     | 19/02/2015 |  21/02/2015

我想对该表执行select语句,但是当begindate不等于enddate时,它必须添加一些行。在上面的示例中,第一行将保持这样,但第二行必须在三行中展开。 select语句的结果必须是:

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

所以我的select语句在这个例子中总共有4行。

有人知道我该怎么做吗?

3 个答案:

答案 0 :(得分:3)

Oracle安装程序

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;

<强>查询

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;

<强>结果:

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 

答案 1 :(得分:1)

以下是直接在桌面上使用connect的替代答案:

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

我建议您测试有效的答案,看看哪个答案对您的数据有最佳效果。

答案 2 :(得分:0)

解决方案与ORACLE SQL:Get all integers between two numbers非常相似,“两个数字”是begindateenddate之间的日期范围。

类似的东西:

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'));

然后

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;