从两个日期列生成日期范围

时间:2019-04-04 03:42:08

标签: sql oracle plsql oracle11g

下面的源表:

Id   start_date   end_date    field1
1    01/03/2019   07/03/2019  text1
2    10/04/2019   15/04/2019  text2

我想得到这个输出:

Id date        field1
1  01/03/2019  text1
1  02/03/2019  text1
1  03/03/2019  text1
1  04/03/2019  text1
1  05/03/2019  text1
1  06/03/2019  text1
1  07/04/2019  text1
2  10/04/2019  text2
2  11/04/2019  text2
2  12/04/2019  text2
2  13/04/2019  text2
2  14/04/2019  text2
2  15/04/2019  text2

我必须使用循环来填充此表吗?

谢谢

2 个答案:

答案 0 :(得分:6)

您可以使用prior + sys_guid()技巧来使用connect by查询

select id,start_date + level - 1 as "date", field1 from t 
connect by level <= end_date - start_date  + 1
    and prior id = id
and prior sys_guid() is not null;

DEMO

答案 1 :(得分:1)

您可以使用SQL标准的递归CTE。例如,以下查询中的CTE var ldetails = _context.RegistrationUsers.Select(x=>new RegistrationUser { PMId=x.PMId, UserName=x.UserName, Password=x.Password, Token=x.Token, ListFriends=x.ListFriends.Select(q => new ListFriend { UserId=q.UserId, UserFriendName=q.UserFriendName, MessagesDetails=q.Where(a => a.TextMessage == messagesDetail.TextMessage).ToList() }).ToList() }).SingleOrDefault(c => c.UserName == Context.User.Identity.Name); 在Oracle和Postgres中均适用(整个查询仅在Oracle中有效,在删除expanded并添加from dual之后将在Postgres中使用):

with recursive

请参见https://dbfiddle.uk/?rdbms=oracle_18&fiddle=c0e49c2fff9e24fee8401e8ac9a16ceb

注意:由于Oracle CTE dating arithmetic bug,该查询在Oracle 11.2之前的版本中将不起作用(由于日期向下错误,您将获得with original as ( select 1 as id, date '2019-03-01' as start_date, date '2019-03-07' as end_date, 'text1' as field from dual union select 2 as id, date '2019-04-10' as start_date, date '2019-04-15' as end_date, 'text2' as field from dual ), expanded (id, the_date, end_date, field) as ( select id, start_date, end_date, field from original union all select original.id, expanded.the_date + 1, original.end_date, original.field from expanded join original on expanded.id = original.id and expanded.the_date + 1 <= original.end_date ) select id, the_date, field from expanded order by id, the_date 错误)。如果您使用的是较早的Oracle版本,则使用connect by可能会更好,因为使用CTE需要一些解决该错误的方法(反向或预先计算的序列),这也很棘手。对于较新的Oracle版本(或其他供应商-如果有人发现此问题),我建议您首选SQL标准方式。