我有一个表,其中包含按账户划分的开始日期和结束日期的账户所有权,但是,有些账户存在重复,有些账户的规则与日期范围重叠。我需要一个干净的结果集显示帐户,所有者,开始日期和结束日期没有重复或重叠。源表如下所示:
帐号 | 开始日期 | 结束日期所有者 | ||
---|---|---|---|---|
1 | 2012年3月1日 | 2012年6月30日约翰·|||
1 | 2012年3月1日 | 2012年6月30日约翰|||
1 | 2012年5月31日 | 2015年7月31日 | 约翰 | |
2 | 2012年5月1日 | <2012年8月1日>账单 | ||
2 | 2012年8月2日 | 2012年10月31日账单 | ||
2 | 2012年1月12日 | joe | ||
2 | 2013年1月1日 | 2025年12月31日 | 账单
表结构有点有趣,虽然有更好的方法可以用更少的代码(即基于集合(来解决这个问题;这就奏效了。这是我的解释和代码。
思考过程:我需要按AccountNumber和Owner的顺序排列行,并确定这两个行中的任何一个更改,因为这将标记一个新的";术语";;此外,我还需要一种方法来标记这些";术语";。对于前者,我使用了ROW_NUMBER
,对于后者,我使用LAG
。这些记录以及2个新字段被插入到临时表中
有了这两条信息,我可以使用WHILE
循环遍历行,跟踪当前行以及学期的最新开始。我用最新的结束日期更新每个学期的第一条记录(假设你没有更早的结束日期和较晚的开始日期(,完成后,我们只选择标记为新学期的记录,我们就会得到你要求的结果集。
文档链接
RowNumber((
滞后
时
代码示例:
DECLARE @RowNumber INTEGER
,@BeginTerm INTEGER
,@EndDate DATE;
DROP TABLE IF EXISTS #OwnershipChange;
SELECT
r.accountNumber
,r.startDate
,r.endDate
,a.employeename AS [owner]
,ROW_NUMBER()OVER(ORDER BY r.accountNumber, r.StartDate) RowNumber
,0 AS Processed
,CASE
WHEN a.employeename = LAG(a.employeename,1,NULL) OVER(ORDER BY r.accountNumber)
AND r.accountNumber = LAG(r.accountNumber,1,NULL)OVER(ORDER BY r.accountNumber)
THEN 0
ELSE 1
END AS NewOwnership
INTO #OwnershipChange
FROM dbo.ruleset r
LEFT OUTER JOIN dbo.rule a ON r.id = a.rulesetid
WHERE a.roleid = '1'
AND r.isapproved = 'true';
WHILE EXISTS (
SELECT 1/0
FROM #OwnershipChange
WHERE Processed = 0
)
BEGIN
SET @RowNumber = (
SELECT TOP 1 RowNumber
FROM #OwnershipChange
WHERE Processed = 0
ORDER BY RowNumber
);
SET @BeginTerm = (
SELECT
CASE
WHEN NewOwnership = 1 THEN @RowNumber
ELSE @BeginTerm
END
FROM #OwnershipChange
WHERE RowNumber = @RowNumber
);
SET @EndDate = (
SELECT endDate
FROM #OwnershipChange
WHERE RowNumber = @RowNumber
);
UPDATE #OwnershipChange
SET endDate = @EndDate
WHERE RowNumber = @BeginTerm;
UPDATE #OwnershipChange
SET Processed = 1
WHERE RowNumber = @RowNumber;
END;
SELECT
accountNumber
,startDate
,endDate
,[owner]
FROM #OwnershipChange
WHERE NewOwnership = 1;