我想将以下日期转换为不同的日期范围,此处emp属于2019年5月25日至2099-02-14年之间的钦奈地区,但介于emp之间,emp在2020-02-15年至2020年之间由DEL工作-02-23。
所以我想将以上日期转换为以下日期范围
我已经在SQL Server中尝试过以下方法,并且可以使用:
测试设置
CREATE TABLE Employee(EmployeeId INT, fromDate date, todate date, Placename VARCHAR(100), PlaceCode VARCHAR(100))
INSERT INTO Employee
VALUES(1111,'2019-07-25','2099-02-14','CHENNAI','MAA'),
(1111,'2020-02-15','2020-02-23','DELHI','DEL');
要执行的查询
;WITH CTE_Ranges AS
(
SELECT EmployeeId, fromdate, lag(fromdate,1) OVER(PARTITION BY EmployeeId ORDER BY fromdate) previousfromDate,todate
, lead(todate,1) OVER(PARTITION BY EmployeeId ORDER BY todate) nexttodate, placename, placecode from Employee
)
--Handle the Maximum and minimum dates
SELECT * FROM
(
SELECT EmployeeId, fromdate, DATEADD(day,-1,lead(fromdate) over(partition by EmployeeId ORDER BY fromDate)) as todate, PlaceName, PlaceCode
FROM CTE_Ranges
UNION ALL
SELECT EmployeeId, DATEADD(day,1,lag(todate) over(partition by EmployeeId ORDER BY todate)) as fromdate, todate,PlaceName, PlaceCode
FROM CTE_Ranges) AS t
WHERE fromdate is not null and todate is not null
UNION ALL
--Now handle normal date ranges
SELECT EmployeeId, fromDate,todate, placename, placecode
from cte_ranges
WHERE previousfromdate is not null and nexttodate is not null
order by fromdate
结果集
+------------+------------+------------+-----------+-----------+
| EmployeeId | fromdate | todate | PlaceName | PlaceCode |
+------------+------------+------------+-----------+-----------+
| 1111 | 2019-07-25 | 2020-02-14 | CHENNAI | MAA |
| 1111 | 2020-02-15 | 2020-02-23 | DELHI | DEL |
| 1111 | 2020-02-24 | 2099-02-14 | CHENNAI | MAA |
+------------+------------+------------+-----------+-----------+
要处理多层嵌套,可以取消数据透视和
with e as (
-- unpivot the dates
select employeeid, fromdate as dte,
placename, placecode
from t
union all
select employeeid, enddate, null, null
from t
),
e2 as (
-- impute the intermediate placenames
select e.*,
max(placename) over (partition by employeeid, grp) as imputed_placename
from (select e.*,
count(placename) over (partition by employeeid order by dte) as grp
from e
) e
)
select employeeid, fromdate,
dateadd(day, -1, lead(fromdate) over (partition by employeeid order by dte)) as enddate,
placename, placecode
from e1;