假设我有两张桌子:
薪酬:
PersonId, StartDate, EndDate, Salary
标题:
PersonId, StartDate, EndDate, Title
一个人的工资与他的头衔无关,可以随时改变。
如何最好地获得薪资和职称不变的所有连续StartDate / EndDate时间间隔?
所以这......
薪酬
Me | 2017-01-01 | 2017-01-31 | 2000
Me | 2017-02-01 | 2017-05-31 | 2100
Me | 2017-06-01 | 2017-07-31 | 2300
标题
Me | 2017-01-01 | 2017-03-31 | Junior
Me | 2017-04-01 | 2017-07-31 | Senior
将返回:
SalaryAndTitle
Me | 2017-01-01 | 2017-01-31 | 2000 | Junior
Me | 2017-02-01 | 2017-03-31 | 2100 | Junior
Me | 2017-04-01 | 2017-05-31 | 2100 | Senior
Me | 2017-06-01 | 2017-07-31 | 2300 | Senior
这是一个简化的例子。在我的实际情况中,会有许多更改列,并且结果数据集仍应包含时间间隔,其中这些列相对于该时间段具有未更改的值。
我正在考虑over( partition by...)
,但我无法让它发挥作用。任何帮助表示赞赏。
干杯,
金
答案 0 :(得分:0)
我不知道你的性能要求,我相信会有更好的方法,但是......
一种解决这些问题的方法是每天将其分解,然后使用标准聚合函数,例如下面我假设您有一个名为日期的表,其中包含您感兴趣的所有日期: / p>
select
p.personid
,min(ds.dt) as from
,max(ds.dt) as to
,s.salary
,t.title
from
dates as ds
cross join
(select distinct personid from salary) as p
left outer join salary as s
on ds.dt >= s.startdate
and ds.dt <= s.enddate
and p.personid = s.personid
left outer join title as t
on ds.dt >= t.startdate
and ds.dt <= t.enddate
and p.personid = t.personid
group by
p.personid
,s.salary
,t.title
我在这里使用左外连接,因为我将从那开始并对数据进行一些分析。
我使用这种类型的东西进行分析,报告和数据迁移。我也用它进行计费计算 - 但是我完全没有对这种方法进行性能测试。重点是编写易于维护的查询,并拥有您可能想要的所有功能(分析往往更容易使用高度非标准化的数据,如日常故障)
答案 1 :(得分:0)
我在示例数据中添加了一些记录,以解决围绕PersonID
具有多个时间范围的可能性的问题,其中PersonID
具有相同的Title
和{{ 1}}。
<强>答案:强>
Salary
子查询会复制create table dbo.Salary
(
PersonID varchar(3)
, StartDate date
, EndDate date
, Salary int
)
create table dbo.Title
(
PersonID varchar(3)
, StartDate date
, EndDate date
, Title varchar(10)
)
insert into dbo.Salary
values ('Me', '2017-01-01', '2017-01-31', 2000)
, ('Me', '2017-02-01', '2017-05-31', 2100)
, ('Me', '2017-06-01', '2017-07-31', 2300)
, ('You', '2017-01-01', '2017-03-31', 2400)
, ('You', '2017-04-01', '2017-08-31', 2500)
, ('You', '2017-09-01', '2017-12-31', 2400)
insert into dbo.Title
values ('Me', '2017-01-01', '2017-03-31', 'Junior')
, ('Me', '2017-04-01', '2017-07-31', 'Senior')
, ('You', '2017-01-01', '2017-02-28', 'Junior')
, ('You', '2017-03-01', '2017-05-31', 'Senior')
, ('You', '2017-06-01', '2017-12-31', 'Junior')
select a.PersonID
, a.StartDate
, a.EndDate
, a.Salary
, a.Title
from (
select s.PersonID
, iif(s.StartDate < t.StartDate, t.StartDate, s.StartDate) as StartDate
, iif(s.EndDate < t.EndDate, s.EndDate, t.EndDate) as EndDate
, s.Salary
, t.Title
from dbo.Salary as s
inner join dbo.Title as t on s.PersonID = t.PersonID
) as a
where 1=1
and datediff(d, a.StartDate, a.EndDate) >= 0 --is it a valid time range?
的所有可能的StartDate
/ EndDate
组合,外部查询会确定该时间范围是否有效。
<强>输出:强>
PersonID