Sql 在不同的行中展开一行

Sql 在不同的行中展开一行,sql,oracle,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语句的结果必须是

我正在开发一个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行


有人知道我该怎么做吗?

解决方案非常类似,两个数字是begindate和enddate之间的日期跨度

比如:

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;

解决方案非常类似于,两个数字是begindate和enddate之间的日期跨度

比如:

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;
Oracle安装程序:

查询:

Oracle安装程序:

查询:


下面是一个替代答案,可在表中直接使用connect by:

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

我建议您测试那些有效的答案,看看哪一个对您的数据性能最好。

这里有一个替代答案,可以直接在表中使用connect by:

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

我建议您测试哪些答案有效,看看哪一个对您的数据性能最好。

一个包含可能日期的帮助表可能会有所帮助。正如jarlh所说,如果您有一个包含全年日期的时间维度,您可以加入。一个包含可能日期的帮助表可能会有所帮助。如jarlh所说,如果您有一个包含所有年份日期的时间维度,则可以加入up.SELECT语句,该语句失败,原因是:SQL Fehler:ORA-00933:SQL命令未正确结束00933。00000-SQL命令未正确endedCROSS APPLY仅在Oracle 12中有效。抱歉,目前无法亲自测试。SELECT语句失败,原因是:SQL Fehler:ORA-00933:SQL命令未正确结束00933。00000-SQL命令未正确endedCROSS APPLY仅在Oracle 12中有效。很抱歉,目前无法亲自测试它。对于此示例,我还有另一个问题。我想添加一列,说明它是块的第一项、中间项、结束项还是唯一项。例如,在上述示例中:2月19日为第一项,2月20日为中间项,2月21日为最后一项。2月18日不是一个期间,因此标志应仅为item.CASE当e.begindate=e.enddate时,然后为'only',当t.COLUMN\u VALUE=e.begindate时,然后为'first',当t.COLUMN\u VALUE=e.enddate时,则为'last',否则为'middle'ENDI对于此示例还有另一个问题。我想添加一列,说明它是块的第一项、中间项、结束项还是唯一项。例如,在上述示例中:2月19日为第一项,2月20日为中间项,2月21日为最后一项。2月18日不是一个期间,因此标志应仅为item.CASE当e.begindate=e.enddate时,然后为'only',当t.COLUMN\u VALUE=e.begindate时,然后为'first',当t.COLUMN\u VALUE=e.enddate时,则为'last',否则为'middle'结束