我的知识非常基础,因此将非常感谢您的帮助。
我试图在满足条件时多次返回同一行(我只能选择查询)。
我有一个包含Customer ID, Start Date and End Date
的500000条记录的表,其中end date
可能是null
。
我正在尝试添加一个名为Week_No
的新列,并相应列出所有行。例如,如果日期范围超过一个星期,则必须使用相应的星期数多次返回该行。另外,我想计算重叠的天数,即每行永远不超过7(周),然后使用第二张表计算不可用的天数。
下面的示例数据
t1
ID | Start_Date | End_Date 000001 | 12/12/2017 | 03/01/2018 000002 | 13/01/2018 | 000003 | 02/01/2018 | 11/01/2018 ...
t2
ID | Unavailable 000002 | 14/01/2018 000003 | 03/01/2018 000003 | 04/01/2018 000003 | 08/01/2018 ...
我无法通过添加星期几的阶段。我曾尝试使用CASE
和UNION ALL
,但一直收到错误消息。
declare @week01start datetime = '2018-01-01 00:00:00'
declare @week01end datetime = '2018-01-07 00:00:00'
declare @week02start datetime = '2018-01-08 00:00:00'
declare @week02end datetime = '2018-01-14 00:00:00'
...
SELECT
ID,
'01' as Week_No,
'2018' as YEAR,
Start_Date,
End_Date
FROM t1
WHERE (Start_Date <= @week01end and End_Date >= @week01start)
or (Start_Date <= @week01end and End_Date is null)
UNION ALL
SELECT
ID,
'02' as Week_No,
'2018' as YEAR,
Start_Date,
End_Date
FROM t1
WHERE (Start_Date <= @week02end and End_Date >= @week02start)
or (Start_Date <= @week02end and End_Date is null)
...
新表应如下所示
ID | Week_No | Year | Start_Date | End_Date | Overlap | Unavail_Days 000001 | 01 | 2018 | 12/12/2017 | 03/01/2018 | 3 | 000002 | 02 | 2018 | 13/01/2018 | | 2 | 1 000003 | 01 | 2018 | 02/01/2018 | 11/01/2018 | 6 | 2 000003 | 02 | 2018 | 02/01/2018 | 11/01/2018 | 4 | 1 ...
答案 0 :(得分:0)
从商业角度来看,我无法理解您要实现的目标。您可以使用以下代码来计算您的重叠天数等。我按照您的要求进行了操作,但是我建议您使用单独的表,例如Time维度,以产生“更清洁”的解决方案
/*sample data set in temp table*/
select '000001' as id, '2017-12-12'as start_dt, ' 2018-01-03' as end_dt into #tmp union
select '000002' as id, '2018-01-13 'as start_dt, null as end_dt union
select '000003' as id, '2018-01-02' as start_dt, '2018-01-11' as end_dt
/*calculate week numbers and week diff according to dates*/
select *,
DATEPART(WK,start_dt) as start_weekNumber,
DATEPART(WK,end_dt) as end_weekNumber,
case
when DATEPART(WK,end_dt) - DATEPART(WK,start_dt) > 0 then (DATEPART(WK,end_dt) - DATEPART(WK,start_dt)) +1
else (52 - DATEPART(WK,start_dt)) + DATEPART(WK,end_dt)
end as WeekDiff
into #tmp1
from
(
SELECT *,DATEADD(DAY, 2 - DATEPART(WEEKDAY, start_dt), CAST(start_dt AS DATE)) [start_dt_Week_Start_Date],
DATEADD(DAY, 8 - DATEPART(WEEKDAY, start_dt), CAST(start_dt AS DATE)) [startdt_Week_End_Date],
DATEADD(DAY, 2 - DATEPART(WEEKDAY, end_dt), CAST(end_dt AS DATE)) [end_dt_Week_Start_Date],
DATEADD(DAY, 8 - DATEPART(WEEKDAY, end_dt), CAST(end_dt AS DATE)) [end_dt_Week_End_Date]
from #tmp
) s
/*cte used to create duplicates when week diff is over 1*/
;with x as
(
SELECT TOP (10) rn = ROW_NUMBER() --modify the max you want
OVER (ORDER BY [object_id])
FROM sys.all_columns
ORDER BY [object_id]
)
/*final query*/
select --*
ID,
start_weekNumber+ (r-1) as Week,
DATEPART(YY,start_dt) as [YEAR],
start_dt,
end_dt,
null as Overlap,
null as unavailable_days
from
(
select *,
ROW_NUMBER() over (partition by id order by id) r
from
(
select d.* from x
CROSS JOIN #tmp1 AS d
WHERE x.rn <= d.WeekDiff
union all
select * from #tmp1
where WeekDiff is null
) a
)a_ext
order by id,start_weekNumber
--drop table #tmp1,#tmp
以上将产生所需的结果,但重叠和不可用的列除外。我不只是计算周数,还使用start_dt添加了一年中的周数,但是如果您不喜欢它,可以更改它:
ID Week YEAR start_dt end_dt Overlap unavailable_days
000001 50 2017 2017-12-12 2018-01-03 NULL NULL
000001 51 2017 2017-12-12 2018-01-03 NULL NULL
000001 52 2017 2017-12-12 2018-01-03 NULL NULL
000002 2 2018 2018-01-13 NULL NULL NULL
000003 1 2018 2018-01-02 2018-01-11 NULL NULL
000003 2 2018 2018-01-02 2018-01-11 NULL NULL