如何判断一份合同是否跨行有效?
How to determine if a contract is valid across multiple lines?
我正在尝试写一些 SQL 来确定和分组合同是否在多个不同的行中有效。
场景如下,我有一个 table 存储有效期为 364 天的合同。有一行用于合同的初始启动,然后一行用于续订。当合同过期或关闭时,还有另一行关闭。有两种不重叠的合同。如果此人转到另一份合同,则旧合同将被关闭。合同没有唯一标识,但人有唯一 ID。
下面是我查看数据的结果。
SELECT CA.ConDate, CA.IsCon, DATEADD(MILLISECOND, 10 * CA.IsCon, CA.ConDate), CA.RenewalStatus, CA.PersonID
FROM dbo.ConActivity CA
WHERE CA.RenewalStatus IN ( 1, 2 )
AND CA.PersonID = '254915C5-2F30-40C9-B7E9-0239E6CBE27B'
ORDER BY DATEADD(MILLISECOND, 10 * CA.IsCon, CA.ConDate)
这returns结果如下:
ConDate IsCon (No column name) RenewalStatus PersonID
2018-01-12 00:00:00.000 0 2018-01-12 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-03-30 00:00:00.000 0 2018-03-30 00:00:00.000 2 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-06-26 00:00:00.000 0 2018-06-26 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-07-26 00:00:00.000 0 2018-07-26 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-07-02 00:00:00.000 0 2019-07-02 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-10-29 00:00:00.000 0 2019-10-29 00:00:00.000 2 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-10-29 00:00:00.000 1 2019-10-29 00:00:00.010 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
续订状态:1 = 已续订(或已打开),2 = 已关闭
从数据中可以看出,合约可以先开后关一段时间(也就是一个时间段),然后在同一个合约类型下开仓续签几次,然后再转换成另一种合约类型合同(那是另一个时间段),然后在新合同类型中打开一个新合同并保持打开状态,直到关闭 RwnewalStatus (= 2)。 (无列名)只是我按正确顺序排列的行和我尝试用来确定时间范围的方法。
我想要每人每合同有效期一行,在这种情况下我想看到:
ConDate IsCon ConEndDate PersonID
2018-01-12 00:00:00.000 0 2018-03-30 00:00:00.000 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-06-26 00:00:00.000 0 2019-10-29 00:00:00.000 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-10-29 00:00:00.000 1 NULL 254915C5-2F30-40C9-B7E9-0239E6CBE27B
你会如何实现这个结果?
假设您的 DBMS 支持 Windowed Aggregates:
with cte as
(
SELECT CA.ConDate, CA.IsCon,
DATEADD(MILLISECOND, 10 * CA.IsCon, CA.ConDate) as col,
CA.RenewalStatus, CA.PersonID,
-- assign the same value to all rows of 1 followed by 2 using a Cumulative Sum
sum(case when RenewalStatus = 2 then 1 else 0 end)
over (partition by PersonID
order by ConDate desc, RenewalStatus
rows unbounded preceding) as grp
FROM tab CA
WHERE CA.RenewalStatus IN ( 1, 2 )
AND CA.PersonID = '254915C5-2F30-40C9-B7E9-0239E6CBE27B'
)
select min(ConDate), max(IsCon),
case when max(RenewalStatus) = 2 then max(ConDate) end, PersonID
from cte
-- now aggregate over the person and the group's value
group by PersonId, grp
我正在尝试写一些 SQL 来确定和分组合同是否在多个不同的行中有效。
场景如下,我有一个 table 存储有效期为 364 天的合同。有一行用于合同的初始启动,然后一行用于续订。当合同过期或关闭时,还有另一行关闭。有两种不重叠的合同。如果此人转到另一份合同,则旧合同将被关闭。合同没有唯一标识,但人有唯一 ID。
下面是我查看数据的结果。
SELECT CA.ConDate, CA.IsCon, DATEADD(MILLISECOND, 10 * CA.IsCon, CA.ConDate), CA.RenewalStatus, CA.PersonID
FROM dbo.ConActivity CA
WHERE CA.RenewalStatus IN ( 1, 2 )
AND CA.PersonID = '254915C5-2F30-40C9-B7E9-0239E6CBE27B'
ORDER BY DATEADD(MILLISECOND, 10 * CA.IsCon, CA.ConDate)
这returns结果如下:
ConDate IsCon (No column name) RenewalStatus PersonID
2018-01-12 00:00:00.000 0 2018-01-12 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-03-30 00:00:00.000 0 2018-03-30 00:00:00.000 2 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-06-26 00:00:00.000 0 2018-06-26 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-07-26 00:00:00.000 0 2018-07-26 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-07-02 00:00:00.000 0 2019-07-02 00:00:00.000 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-10-29 00:00:00.000 0 2019-10-29 00:00:00.000 2 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-10-29 00:00:00.000 1 2019-10-29 00:00:00.010 1 254915C5-2F30-40C9-B7E9-0239E6CBE27B
续订状态:1 = 已续订(或已打开),2 = 已关闭
从数据中可以看出,合约可以先开后关一段时间(也就是一个时间段),然后在同一个合约类型下开仓续签几次,然后再转换成另一种合约类型合同(那是另一个时间段),然后在新合同类型中打开一个新合同并保持打开状态,直到关闭 RwnewalStatus (= 2)。 (无列名)只是我按正确顺序排列的行和我尝试用来确定时间范围的方法。
我想要每人每合同有效期一行,在这种情况下我想看到:
ConDate IsCon ConEndDate PersonID
2018-01-12 00:00:00.000 0 2018-03-30 00:00:00.000 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2018-06-26 00:00:00.000 0 2019-10-29 00:00:00.000 254915C5-2F30-40C9-B7E9-0239E6CBE27B
2019-10-29 00:00:00.000 1 NULL 254915C5-2F30-40C9-B7E9-0239E6CBE27B
你会如何实现这个结果?
假设您的 DBMS 支持 Windowed Aggregates:
with cte as
(
SELECT CA.ConDate, CA.IsCon,
DATEADD(MILLISECOND, 10 * CA.IsCon, CA.ConDate) as col,
CA.RenewalStatus, CA.PersonID,
-- assign the same value to all rows of 1 followed by 2 using a Cumulative Sum
sum(case when RenewalStatus = 2 then 1 else 0 end)
over (partition by PersonID
order by ConDate desc, RenewalStatus
rows unbounded preceding) as grp
FROM tab CA
WHERE CA.RenewalStatus IN ( 1, 2 )
AND CA.PersonID = '254915C5-2F30-40C9-B7E9-0239E6CBE27B'
)
select min(ConDate), max(IsCon),
case when max(RenewalStatus) = 2 then max(ConDate) end, PersonID
from cte
-- now aggregate over the person and the group's value
group by PersonId, grp