如何为日期范围内的每个月创建新行?
How to create new rows for each month within a date range?
我需要创建一个视图,为日期范围内的每个月创建新行。
我的预订 table 的数据示例如下所示。
Booking ID Booking Name Start Date End Date Booked Days
1 HolidayUSA 1/01/2020 15/02/2020 46
2 HolidayEurope 20/01/2020 10/03/2020 50
3 HolidayUK 14/03/2020 19/03/2020 5
我想创建一个视图,为日期范围内的每个月添加一条新记录,根据该月的天数计算预订天数,并添加 month/year 个字段。
预期输出:
我正在使用 Microsoft SQL 服务器。
任何帮助将不胜感激。
这是我最接近的近似值:
declare @tb table ([Booking Id] int, [Booking Name] varchar(30),
[Start Date] datetime, [End Date] datetime)
-- Sample data
insert @tb values
(1, 'HolidayUSA','20200101','20200215'),
(2, 'HolidayEUROPE','20200120','20200310'),
(3, 'HolidayUK','20200314','20200319')
-- Showing sample data
select *, dateDiff(dd, [Start Date], [End Date]) [Booked Days]
from @tb
declare @dd smallint
select @dd = max(dateDiff(dd, [Start Date], [End Date])) from @tb
with day_cte as (
select 1 as nbd union all
select nbd + 1 from day_cte where nbd <= @dd)
select [Booking Id], [Booking Name], [Start Date], [End Date]
, datePart(yy, dateAdd(dd, nbd, [Start Date])) [Year]
, left(dateName(mm, dateAdd(dd, nbd, [Start Date])), 3) [Month]
, count(*) [Booked Days]
from @tb, day_cte
where nbd <= dateDiff(dd, [Start Date], [End Date])
group by [Booking Id], [Booking Name], [Start Date], [End Date]
, datePart(yy, dateAdd(dd, nbd, [Start Date]))
, dateName(mm, dateAdd(dd, nbd, [Start Date]))
这是一个基于计数或数字 table 的方法。理货 CTE 创建一个序列(最多 12^4 或 20,736 天(可以增加到任何必要的天数))以按天延长日历。然后按月汇总。
;with
n(n) as (select * from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) v(n)),
tally_cte(N) as (
select row_number() over (order by (select null))
from n n1 cross join n n2 cross join n n3 cross join n n4)
select booking_id, booking_name, start_dt, end_dt, dfp.dfp,
year(dt.booking_dt) [Year], convert(char(3), dt.booking_dt, 0) [Month],
count(*) booked_days
from #test t
cross apply
(select dateadd(d, n-1, t.start_dt) booking_dt
from tally_cte
where n<=datediff(d, t.start_dt, t.end_dt)) dt
cross apply
(select datefromparts(year(dt.booking_dt), month(dt.booking_dt), 1) dfp) dfp
group by booking_id, booking_name, start_dt, end_dt, dfp.dfp,
year(dt.booking_dt), convert(char(3), dt.booking_dt, 0)
order by 1, 3, 5;
输出
booking_id booking_name start_dt end_dt dfp Year Month booked_days
1 HolidayUSA 2020-01-01 2020-02-15 2020-01-01 2020 Jan 31
1 HolidayUSA 2020-01-01 2020-02-15 2020-02-01 2020 Feb 14
2 HolidayEurope 2020-01-20 2020-03-10 2020-01-01 2020 Jan 12
2 HolidayEurope 2020-01-20 2020-03-10 2020-02-01 2020 Feb 29
2 HolidayEurope 2020-01-20 2020-03-10 2020-03-01 2020 Mar 9
3 HolidayUK 2020-03-14 2020-03-19 2020-03-01 2020 Mar 5
我需要创建一个视图,为日期范围内的每个月创建新行。 我的预订 table 的数据示例如下所示。
Booking ID Booking Name Start Date End Date Booked Days
1 HolidayUSA 1/01/2020 15/02/2020 46
2 HolidayEurope 20/01/2020 10/03/2020 50
3 HolidayUK 14/03/2020 19/03/2020 5
我想创建一个视图,为日期范围内的每个月添加一条新记录,根据该月的天数计算预订天数,并添加 month/year 个字段。
预期输出:
我正在使用 Microsoft SQL 服务器。 任何帮助将不胜感激。
这是我最接近的近似值:
declare @tb table ([Booking Id] int, [Booking Name] varchar(30),
[Start Date] datetime, [End Date] datetime)
-- Sample data
insert @tb values
(1, 'HolidayUSA','20200101','20200215'),
(2, 'HolidayEUROPE','20200120','20200310'),
(3, 'HolidayUK','20200314','20200319')
-- Showing sample data
select *, dateDiff(dd, [Start Date], [End Date]) [Booked Days]
from @tb
declare @dd smallint
select @dd = max(dateDiff(dd, [Start Date], [End Date])) from @tb
with day_cte as (
select 1 as nbd union all
select nbd + 1 from day_cte where nbd <= @dd)
select [Booking Id], [Booking Name], [Start Date], [End Date]
, datePart(yy, dateAdd(dd, nbd, [Start Date])) [Year]
, left(dateName(mm, dateAdd(dd, nbd, [Start Date])), 3) [Month]
, count(*) [Booked Days]
from @tb, day_cte
where nbd <= dateDiff(dd, [Start Date], [End Date])
group by [Booking Id], [Booking Name], [Start Date], [End Date]
, datePart(yy, dateAdd(dd, nbd, [Start Date]))
, dateName(mm, dateAdd(dd, nbd, [Start Date]))
这是一个基于计数或数字 table 的方法。理货 CTE 创建一个序列(最多 12^4 或 20,736 天(可以增加到任何必要的天数))以按天延长日历。然后按月汇总。
;with
n(n) as (select * from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) v(n)),
tally_cte(N) as (
select row_number() over (order by (select null))
from n n1 cross join n n2 cross join n n3 cross join n n4)
select booking_id, booking_name, start_dt, end_dt, dfp.dfp,
year(dt.booking_dt) [Year], convert(char(3), dt.booking_dt, 0) [Month],
count(*) booked_days
from #test t
cross apply
(select dateadd(d, n-1, t.start_dt) booking_dt
from tally_cte
where n<=datediff(d, t.start_dt, t.end_dt)) dt
cross apply
(select datefromparts(year(dt.booking_dt), month(dt.booking_dt), 1) dfp) dfp
group by booking_id, booking_name, start_dt, end_dt, dfp.dfp,
year(dt.booking_dt), convert(char(3), dt.booking_dt, 0)
order by 1, 3, 5;
输出
booking_id booking_name start_dt end_dt dfp Year Month booked_days
1 HolidayUSA 2020-01-01 2020-02-15 2020-01-01 2020 Jan 31
1 HolidayUSA 2020-01-01 2020-02-15 2020-02-01 2020 Feb 14
2 HolidayEurope 2020-01-20 2020-03-10 2020-01-01 2020 Jan 12
2 HolidayEurope 2020-01-20 2020-03-10 2020-02-01 2020 Feb 29
2 HolidayEurope 2020-01-20 2020-03-10 2020-03-01 2020 Mar 9
3 HolidayUK 2020-03-14 2020-03-19 2020-03-01 2020 Mar 5