当月内没有中断或所有权发生变化时,需要获取最小开始日期和最大结束日期

问题描述

我有一个表格,其中包含按帐户划分的开始日期和结束日期的帐户所有权,但是,有些帐户存在重复,有些则具有与日期范围重叠的规则。我需要一个干净的结果集,显示帐户、所有者、开始日期和结束日期,没有重复或重叠。 源表如下所示:

账号 开始日期 结束日期 所有者
1 3/1/2012 6/30/2012 约翰
1 3/1/2012 6/30/2012 约翰
1 5/31/2012 7/31/2015 约翰
2 5/1/2012 8/1/2012 账单
2 8/2/2012 10/31/2012 账单
2 12/1/2012 12/31/2012
2 1/1/2013 12/31/2025 账单

我需要这样的结果

账号 开始日期 结束日期 所有者
1 3/1/2012 7/31/2015 约翰
2 5/1/2012 10/31/2012 账单
2 12/1/2012 12/31/2012
2 1/1/2013 12/31/2025 账单

非常感谢任何帮助。说到 sql,我是个新手。

Select distinct 删除了我的重复项,但我仍然得到多个重叠的日期范围。

我不知道我们使用的是什么版本的 sql server。它是一个名为 Sisense 的 BI 应用程序中的连接器,并没有真正说明。

这是我目前的选择语句:

    select distinct
    r.accountnumber,r.startdate,r.enddate,a.employeename Owner
    from "dbo"."ruleset" r
    left join "dbo"."rule" a on r.id = a.rulesetid
    where 
    a.roleid = '1' and
    r.isapproved = 'true'

解决方法

表结构有点有趣,虽然可能有更好的方法用更少的代码(即基于集合)来解决这个问题;这就是诀窍。这是我的解释和我的代码。

思考过程:我需要按照 AccountNumber 和 Owner 的顺序对行进行排序,并在其中任何一个发生变化时进行识别,因为这会标记一个新的“术语”;另外,我需要一种方法来标记每个“术语”的开头。前者我用了ROW_NUMBER,后者我用了LAG。这些记录以及 2 个新字段被插入到临时表中。
有了这 2 条信息,我就可以使用 WHILE 循环遍历行,跟踪当前行以及术语的最近开头。我用最新的结束日期更新每个学期的第一条记录(假设您没有较早的结束日期用于较晚的开始日期),一旦我们完成,我们只选择标记为新学期的记录,我们得到您要求的结果集。

文档链接。
RowNumber()
Lag
While

代码示例

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,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;