如何根据开始日期和结束日期复制记录
How to Duplicate Records According to Start and End Dates
我在 SQL 数据库中有记录需要扩展 startDate
和 endDate
。
| userName | startDate | endDate | weekDay |
| :---------: | :--------: | :--------: | :-----: |
| Test User 1 | 2011-03-30 | 2011-04-05 | 1 |
| Test User 2 | 2016-10-05 | 2016-10-07 | 5 |
| Test User 3 | 2018-05-22 | 2018-05-26 | 4 |
在上面的table中,每条记录都有涵盖多个日期的信息。我需要的是每个用户每个 一个 日期的 一个 记录。我正在寻找的示例:
| userName | startDate | weekDay |
| :---------: | :--------: | :--------: |
| Test User 1 | 2011-03-30 | 1 |
| Test User 1 | 2011-03-31 | 1 |
| Test User 1 | 2011-04-01 | 1 |
| Test User 1 | 2011-04-02 | 1 |
| Test User 1 | 2011-04-03 | 1 |
| Test User 1 | 2011-04-04 | 1 |
| Test User 1 | 2011-04-05 | 1 |
| Test User 2 | 2016-10-05 | 5 |
| Test User 2 | 2016-10-06 | 5 |
| Test User 2 | 2016-10-07 | 5 |
| Test User 3 | 2018-05-22 | 4 |
| Test User 3 | 2018-05-23 | 4 |
| Test User 3 | 2018-05-24 | 4 |
| Test User 3 | 2018-05-25 | 4 |
| Test User 3 | 2018-05-26 | 4 |
This answer 让我更进一步,指定如何在 SQL 中生成日期序列。如何根据 SQL 中的开始日期和结束日期复制表格记录?
注意,我需要这个解决方案在 MSSQL 和 PostgreSQL 中工作。
您可以在 SQL 服务器和 Postgres 中使用递归 CTE,但语法略有不同。而且,在 Postgres 中有一个更简单的方法。所以,在SQL服务器中,你可以这样做:
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);
如果您需要相同的代码在两者中工作,您需要生成一个数字 table。这是一个(令人不快的)方法:
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 服务器中需要 datetime
,但在 Postgres 中需要 date
。
试试下面的代码。我使用了递归通用 table 表达式。
;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 Fiddle: http://sqlfiddle.com/#!18/fa22a/3
我在 SQL 数据库中有记录需要扩展 startDate
和 endDate
。
| userName | startDate | endDate | weekDay |
| :---------: | :--------: | :--------: | :-----: |
| Test User 1 | 2011-03-30 | 2011-04-05 | 1 |
| Test User 2 | 2016-10-05 | 2016-10-07 | 5 |
| Test User 3 | 2018-05-22 | 2018-05-26 | 4 |
在上面的table中,每条记录都有涵盖多个日期的信息。我需要的是每个用户每个 一个 日期的 一个 记录。我正在寻找的示例:
| userName | startDate | weekDay |
| :---------: | :--------: | :--------: |
| Test User 1 | 2011-03-30 | 1 |
| Test User 1 | 2011-03-31 | 1 |
| Test User 1 | 2011-04-01 | 1 |
| Test User 1 | 2011-04-02 | 1 |
| Test User 1 | 2011-04-03 | 1 |
| Test User 1 | 2011-04-04 | 1 |
| Test User 1 | 2011-04-05 | 1 |
| Test User 2 | 2016-10-05 | 5 |
| Test User 2 | 2016-10-06 | 5 |
| Test User 2 | 2016-10-07 | 5 |
| Test User 3 | 2018-05-22 | 4 |
| Test User 3 | 2018-05-23 | 4 |
| Test User 3 | 2018-05-24 | 4 |
| Test User 3 | 2018-05-25 | 4 |
| Test User 3 | 2018-05-26 | 4 |
This answer 让我更进一步,指定如何在 SQL 中生成日期序列。如何根据 SQL 中的开始日期和结束日期复制表格记录?
注意,我需要这个解决方案在 MSSQL 和 PostgreSQL 中工作。
您可以在 SQL 服务器和 Postgres 中使用递归 CTE,但语法略有不同。而且,在 Postgres 中有一个更简单的方法。所以,在SQL服务器中,你可以这样做:
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);
如果您需要相同的代码在两者中工作,您需要生成一个数字 table。这是一个(令人不快的)方法:
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 服务器中需要 datetime
,但在 Postgres 中需要 date
。
试试下面的代码。我使用了递归通用 table 表达式。
;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 Fiddle: http://sqlfiddle.com/#!18/fa22a/3