很抱歉,如果以前已经回答了这个问题,但是找不到。也许是我的错误关键字。
我有这张桌子:
CREATE TABLE test1
(
Employee VARCHAR(10),
Band VARCHAR(10),
StartDate DATE,
EndDate DATE
)
INSERT INTO test1
VALUES ('Emp1', 'Band1', '2009-01-01', '2010-12-31'),
('Emp1', 'Band1', '2011-01-01', '2012-12-31'),
('Emp1', 'Band1', '2013-01-01', '2013-08-31'),
('Emp1', 'Band2', '2013-09-01', '2013-12-31'),
('Emp1', 'Band2', '2014-01-01', '2014-06-30'),
('Emp1', 'Band1', '2014-07-01', '2014-12-31'),
('Emp1', 'Band1', '2015-01-01', '2018-08-31'),
('Emp2', 'Band1', '2012-01-01', '2014-12-31'),
('Emp2', 'Band1', '2015-01-01', '2018-03-31')
此表中的结果:
Employee Band StartDate EndDate
----------------------------------------
Emp1 Band1 2009-01-01 2010-12-31
Emp1 Band1 2011-01-01 2012-12-31
Emp1 Band1 2013-01-01 2013-08-31
Emp1 Band2 2013-09-01 2013-12-31
Emp1 Band2 2014-01-01 2014-06-30
Emp1 Band1 2014-07-01 2014-12-31
Emp1 Band1 2015-01-01 2018-08-31
Emp2 Band1 2012-01-01 2014-12-31
Emp2 Band1 2015-01-01 2018-03-31
我要创建的是一个结果表,将每个employee
与band
以及最小start date
和最大end date
分组,但是当中间记录时(band
)位于相似的band
之间的中间,end date
应该被封顶,相似{{1}中的下一组start date
}应该再次重置。
band
我尝试过CTE获取每个频段的最大值和最小值,并将其与原始表进行比较,但是我仍然失败。我也尝试使用超前和滞后,但仍然失败。
很高兴
假设第二条记录的Employee Band StartDate EndDate
----------------------------------------
Emp1 Band1 2009-01-01 2013-08-31
Emp1 Band2 2013-09-01 2014-06-30
Emp1 Band1 2014-07-01 2018-08-31
Emp2 Band1 2012-01-01 2018-03-31
是EndDate
,我希望结果仍然是第一Band1组的一条记录。
2012-02-01
结果的每一行仅在Employee Band StartDate EndDate
----------------------------------------
Emp1 Band1 2009-01-01 2013-08-31
中有所不同,因此我能够找出员工在移至其他频段(不同频段)之前在该频段停留了多长时间。
但这真是太好了。
答案 0 :(得分:1)
这通常称为差距和岛屿。
一种方法
示例
Declare @YourTable Table ([Employee] varchar(50),[Band] varchar(50),[Start] date,[End] date)
Insert Into @YourTable Values
('Emp1','Band1','2009-01-01','2010-12-31')
,('Emp1','Band1','2011-01-01','2012-12-31')
,('Emp1','Band1','2013-01-01','2013-08-31')
,('Emp1','Band2','2013-09-01','2013-12-31')
,('Emp1','Band2','2014-01-01','2014-06-30')
,('Emp1','Band1','2014-07-01','2014-12-31')
,('Emp1','Band1','2015-01-01','2018-08-31')
,('Emp2','Band3','2012-01-01','2014-12-31')
,('Emp2','Band3','2015-01-01','2018-03-31')
;with cte as (
Select *,Grp = sum(Flg) over (Partition By Employee Order by [End])
From (
Select *,Flg = IsNull(datediff(DAY,Lag([End],1) over (Partition By Employee,Band Order by [End]) ,[Start]) - 1,1)
From @YourTable
) A
)
Select Employee
,Band
,[Start] = min([Start])
,[End] = max([End])
From cte
Group By Employee,Band,Grp
Order by Employee,max([End])
返回
Employee Band Start End
Emp1 Band1 2009-01-01 2013-08-31
Emp1 Band2 2013-09-01 2014-06-30
Emp1 Band1 2014-07-01 2018-08-31
Emp2 Band3 2012-01-01 2018-03-31
如果有助于可视化,CTE会生成以下内容
注意标志和组列
答案 1 :(得分:1)
显然,每当员工更换乐队时,您都希望对行进行分组。窗口功能很简单。以下解决方案在波段更改时向行添加“ change”标志。请注意,它忽略了差距。将DATEDIFF检查添加到案例陈述中,以找到该人与乐队关联的 actual 时间:
DECLARE @test1 TABLE(
Employee VARCHAR(10),
Band VARCHAR(10),
StartDate DATE,
EndDate DATE
);
INSERT INTO @test1 VALUES
('Emp1', 'Band1', '2009-01-01', '2010-12-31'),
('Emp1', 'Band1', '2011-01-01', '2012-12-31'),
('Emp1', 'Band1', '2013-01-01', '2013-08-31'),
('Emp1', 'Band2', '2013-09-01', '2013-12-31'),
('Emp1', 'Band2', '2014-01-01', '2014-06-30'),
('Emp1', 'Band1', '2014-07-01', '2014-12-31'),
('Emp1', 'Band1', '2015-01-01', '2018-08-31'),
('Emp2', 'Band1', '2012-01-01', '2014-12-31'),
('Emp2', 'Band1', '2015-01-01', '2018-03-31');
WITH cte1 AS (
SELECT *,
CASE WHEN LAG(Band) OVER (PARTITION BY Employee ORDER BY StartDate) = Band /* AND DATEDIFF(...) */ THEN 0 ELSE 1 END AS Chg
FROM @test1
), cte2 AS (
SELECT *,
SUM(Chg) OVER (PARTITION BY Employee ORDER BY StartDate) AS Grp
FROM cte1
)
SELECT Employee, Band, MIN(StartDate), Max(EndDate)
FROM cte2
GROUP BY Employee, Band, Grp
如果您想了解其工作原理,这是中间结果:
| Employee | Band | StartDate | EndDate | Chg | Grp |
|----------|-------|---------------------|---------------------|-----|-----|
| Emp1 | Band1 | 01/01/2009 00:00:00 | 31/12/2010 00:00:00 | 1 | 1 |
| Emp1 | Band1 | 01/01/2011 00:00:00 | 31/12/2012 00:00:00 | 0 | 1 |
| Emp1 | Band1 | 01/01/2013 00:00:00 | 31/08/2013 00:00:00 | 0 | 1 |
| Emp1 | Band2 | 01/09/2013 00:00:00 | 31/12/2013 00:00:00 | 1 | 2 |
| Emp1 | Band2 | 01/01/2014 00:00:00 | 30/06/2014 00:00:00 | 0 | 2 |
| Emp1 | Band1 | 01/07/2014 00:00:00 | 31/12/2014 00:00:00 | 1 | 3 |
| Emp1 | Band1 | 01/01/2015 00:00:00 | 31/08/2018 00:00:00 | 0 | 3 |
| Emp2 | Band1 | 01/01/2012 00:00:00 | 31/12/2014 00:00:00 | 1 | 1 |
| Emp2 | Band1 | 01/01/2015 00:00:00 | 31/03/2018 00:00:00 | 0 | 1 |