如何根据开始和结束日期复制记录

时间:2018-05-16 22:40:35

标签: sql sql-server postgresql date-range

我在SQL数据库中有记录,我需要展开{​​{1}}和declare @max int select @max = max(len(RPVINVNoSpace)) from jde_SupplierInvoices update jde_SupplierInvoices set RPVINVNumeric = '' declare @loop int = 1 while @loop <= @max begin update jde_SupplierInvoices set RPVINVNumeric = RPVINVNumeric + case when substring(RPVINVNoSpace,@loop,1) in ('0','1','2','3','4','5','6','7','8','9') then substring(RPVINVNoSpace,@loop,1) when substring(lower(RPVINVNoSpace),@loop,3) = 'jan' then '01' when substring(lower(RPVINVNoSpace),@loop,3) = 'feb' then '02' when substring(lower(RPVINVNoSpace),@loop,3) = 'mar' then '03' when substring(lower(RPVINVNoSpace),@loop,3) = 'apr' then '04' when substring(lower(RPVINVNoSpace),@loop,3) = 'may' then '05' when substring(lower(RPVINVNoSpace),@loop,3) = 'jun' then '06' when substring(lower(RPVINVNoSpace),@loop,3) = 'jul' then '07' when substring(lower(RPVINVNoSpace),@loop,3) = 'aug' then '08' when substring(lower(RPVINVNoSpace),@loop,3) = 'sep' then '09' when substring(lower(RPVINVNoSpace),@loop,3) = 'oct' then '10' when substring(lower(RPVINVNoSpace),@loop,3) = 'nov' then '11' when substring(lower(RPVINVNoSpace),@loop,3) = 'dec' then '12' else '' end set @loop = @loop + 1 end

startDate

在上表中,每条记录都包含涵盖多个日期的信息。我需要的是每个用户每一个日期一个记录。我正在寻找的一个例子:

endDate

This answer让我更进了一步,详细说明了如何在SQL中生成一系列日期。如何根据SQL中的开始和结束日期复制表格记录?

作为一个注释,我需要这个解决方案在MSSQL和PostgreSQL中工作。

2 个答案:

答案 0 :(得分:1)

您可以在SQL Server和Postgres中使用递归CTE,但语法略有不同。并且,Postgres中有一种更简单的方法。因此,在SQL Server中,您可以执行以下操作:

with cte as (
      select username, startdate, weekday, enddate
      from t
      union all
      select username, dateadd(day, 1, startdate) weekday, enddate
      from cte
      where startdate < enddate
     )
select username, startdate, weekday
from cte
order by username, startdate;

您可以调整日期算术并为Postgres添加recursive关键字。

Postgres中更简单的方法是横向连接:

select t.username, g.startdate, t.weekday
from t, lateral
     generate_series(start_date, end_date, interval '1 day') g(startdate);

如果您需要使用相同的代码,则需要生成数字表。这是一种(令人不愉快的)方法:

with digits as (
      select v.n
      from (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)) v(n)
     ),
     n as (
      select d1.n * 100 + d2.n * 10 + d3.n as n
      from digits d1 cross join digits d2 cross join digits d3
     )
select t.username, t.startdate + n.n, t.weekday
from t join
     n 
     on t.startdate + n.n <= t.enddate;

请注意,要使其工作startdate需要在SQL Server中为datetime,而在Postgres中为date

答案 1 :(得分:0)

尝试以下代码。我使用了递归公用表表达式。

;with cte
AS
(
  SELECT userName,startDate,startDate AS endDate,weekDay FROM tab1
    Union all
  SELECT t1.userName,DATEADD(d,1,t1.startdate) AS startDate,
  DATEADD(d,1,t1.startdate) AS startDate,t1.weekDay
  FROM cte t1
 JOIN tab1 t2 on t1.userName=t2.userName
 WHERE t2.endDate>t1.endDate
) 

 Select userName,startDate,weekDay from cte order by userName

SQL小提琴:http://sqlfiddle.com/#!18/fa22a/3