【问题标题】:Gaps in Date Ranges日期范围的差距
【发布时间】:2019-09-20 19:39:28
【问题描述】:

我有一些租赁信息,包括开始租赁的日期和可能的停止日期(如果没有停止,我们假设仍在租金中)。我还有关于这些项目的发票信息,包括该项目的每张发票的计费周期的开始和停止。

示例数据:

Rental Contract | Item | Rental Start | Rental Stop | Invoice Number | Bill Start | Bill Stop 
1234            |A     | 4/1/2019     |             | 4444           | 4/1/2019   | 4/30/2019  
1234            |A     | 4/1/2019     |             | 4445           | 5/1/2019   | 5/31/2019
1234            |A     | 4/1/2019     |             | 4444           | 6/5/2019   | 6/30/2019
1234            |B     | 4/1/2019     | 5/15/2019   | 4445           | 5/1/2019   | 5/15/2019

我想返回项目 A 缺少 6/1 - 6/4 的期间和项目 B 的 4/1 - 4/30 的错过期间。我需要做的是返回一个数据集返回上面的行,但插入缺失的行,以便在最终报告中突出显示。

这是我需要返回的:

Rental Contract | Item | Rental Start | Rental Stop | Invoice Number | Bill Start | Bill Stop    
1234            |A     | 4/1/2019     |             | 4444           | 4/1/2019   | 4/30/2019     
1234            |A     | 4/1/2019     |             | 4445           | 5/1/2019   | 5/31/2019    
1234            |A     | 4/1/2019     |             |                | 6/1/2019   | 6/4/2019    
1234            |A     | 4/1/2019     |             | 4444           | 6/5/2019   | 4/30/2019    
1234            |B     | 4/1/2019     | 5/15/2019   |                | 4/1/2019   | 4/30/2019    
1234            |B     | 4/1/2019     | 5/15/2019   | 4445           | 5/1/2019   | 5/15/2019

编辑:

所以这就是我尝试过的。我可以缩小到我知道有问题的行并查看差距。我只需要对数据进行更多处理以更改这些数据以显示缺少的开始和停止应该是什么,然后将其合并回原始数据。前几天我无法理解它,看到这里提供的答案帮助了我。谢谢大家。

DECLARE @TicketNumber AS DECIMAL(19, 6) = 109138;

WITH rentals
    AS (SELECT DTH.Rental_Ticket
                                                                            --,DTH.Order_Date
                                                                            --,DTH.Customer_Code
                                                                            --,DTH.Customer_Name
                                                                            --,DTH.Last_Invoice
              ,DTL.Inventory_Item_ID
                                                                            --,DTL.Line_Description AS Ticket_Line_Description
                                                                            --,DTL.Delivery_Date
                                                                            --,DTL.Original_Start_Rent_Date
              ,COALESCE(DTL.Original_Start_Rent_Date, DTL.Delivery_Date, DTH.Order_Date) AS Rental_Start_Date
                                                                            --,dtl.Rental_Stop_Date
                                                                            --,dtl.Return_Date
              ,COALESCE(DTL.Rental_Stop_Date, DTL.Return_Date) AS Rental_Stop_Date
              ,IL.Invoice_Number
              ,LAG(IL.Rental_Stop_Date) OVER (PARTITION BY DTH.Rental_Ticket
                                                          ,DTL.Inventory_Item_ID
                                              ORDER BY DTH.Rental_Ticket
                                                      ,DTL.Inventory_Item_ID
                                                      ,IL.Billing_Cycle_Period_Start_DateTime
                                                      ,IL.Rental_Stop_Date) AS Prev_Stop_Bill_Date
              ,IL.Billing_Cycle_Period_Start_DateTime AS Billing_Start_Date --Invoice_Billing_Start
              ,IL.Rental_Stop_Date AS Billing_Stop_Date                     --Invoice_Billing_Stop
              ,LEAD(IL.Rental_Stop_Date) OVER (PARTITION BY DTH.Rental_Ticket
                                                           ,DTL.Inventory_Item_ID
                                               ORDER BY DTH.Rental_Ticket
                                                       ,DTL.Inventory_Item_ID
                                                       ,IL.Billing_Cycle_Period_Start_DateTime
                                                       ,IL.Rental_Stop_Date) AS Next_Start_Bill_Date

        --,il.Billing_Logic_Itype
        --,il.Line_Description AS Invoice_Line_Description
        --,il.Gross_Line_Pre_Tax_Total
        FROM dbo.CSView_DEL_Ticket_Header_Master AS DTH
            LEFT JOIN dbo.CSView_DEL_Ticket_Lines_Master AS DTL
                ON DTH.Rental_Ticket = DTL.Rental_Ticket
            LEFT JOIN dbo.CSView_INVC_Lines_Master AS IL
                ON DTL.Rental_Ticket = IL.Rental_Ticket_or_Tag_Number
                    AND DTL.Rental_Ticket_Unique_Line_ID = IL.Rental_Ticket_Unique_Line_ID_or_Tag_OrigCounter
        WHERE DTH.Ticket_Type IN ('D', 'T')
            AND DTH.Rental_Ticket NOT IN
                  (SELECT DV.dticket
                   FROM dbo.deltick_void AS DV)
            AND IL.Billing_Logic_Itype <> 'C'
            -- AND DTH.Order_Date BETWEEN '4/1/2018' AND '9/20/2018'
            AND DTH.Rental_Ticket = @TicketNumber)
SELECT R.Rental_Ticket
      ,R.Inventory_Item_ID
      ,R.Rental_Start_Date
      ,R.Rental_Stop_Date
      ,R.Invoice_Number
      ,R.Prev_Stop_Bill_Date
      ,R.Billing_Start_Date
      ,R.Billing_Stop_Date
      ,R.Next_Start_Bill_Date
FROM rentals AS R
WHERE (R.Rental_Start_Date <> R.Billing_Start_Date
          AND R.Prev_Stop_Bill_Date IS NULL) --first billing where there is a gap between rental start and bill start
    OR (DATEADD(DAY, 1, R.Prev_Stop_Bill_Date) <> R.Billing_Start_Date) --where there is a gap between last billing stop and current billing start
ORDER BY R.Rental_Ticket
        ,R.Inventory_Item_ID
        ,R.Billing_Start_Date
        ,R.Billing_Stop_Date

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 定义什么是“错过的时期”。
  • 错过的时间是当账单停止后没有立即开始同一合同/项目的(不同)账单开始并且租赁没有停止。
  • 错过的期间是指发票日期范围内的间隔。因此,如果一个发票范围是 2019 年 4 月 1 日 - 2019 年 4 月 1 日 - 2019 年 4 月 1 日,而下一个范围是 2019 年 5 月 1 日 - 2019 年 5 月 30 日,则错过的时间段。错过的时间是 4/16 - 4/30。如果租金从 4 月 1 日开始,但第一张发票直到 5 月 1 日才开出,情况也是如此,因此整个 4 月都是错过的时期。
  • 就我所尝试的而言,我玩的是滞后和领先,但就是无法正确地写出来让我找到差距。

标签: sql sql-server gaps-and-islands gaps-in-data


【解决方案1】:

如果我理解正确,您可以使用以下方法找出差距:

select contract, item, billstart, dateadd(day, -1, rentalstart) as billend
from t
where billstart < rentalstart
union all
select contract, item, dateadd(day, 1, rentalend) as billstart, billend
from t
where billend > rentalend;

然后您可以合并原始数据并选择您实际需要的列以获得最终结果集。

【讨论】:

    【解决方案2】:

    我认为这可以做到。内嵌评论。

    declare @Rentals table (contract int, item varchar(1), rentstart date, rentstop date, invoice int, billstart date, billstop date)
    
    insert into @Rentals
        values (1234,'A','2019-04-01',null,4444,'2019-04-01','2019-04-30')
            ,(1234,'A','2019-04-01',null,4445,'2019-05-01','2019-05-31')
            ,(1234,'A','2019-04-01',null,4444,'2019-06-05','2019-06-30')
            ,(1234,'B','2019-04-01','2019-05-15',4445,'2019-05-01','2019-05-15')
    
    -- Start with the known data
    select *
    from @rentals r
    
    union all
    
    ( -- union all to add the gaps in the bills
        select contract,item,rentstart,rentstop,null invoice,dateadd("dd",1,billstop) billstart, dateadd("dd",-1,nextstart) billstop
        from (  -- use the min billstart to get the next closest start after the bill end
            select (select min(r2.billstart) from @rentals r2 where r2.item=r.item and r2.contract=r.contract and r2.billstart > r.billstop) nextstart,*
            from @rentals r
        ) a
        where dateadd("dd",1,billstop) <> nextstart -- there is no gap if the next bill starts the day after the current bill ends
    )
    
    union all
    
    ( -- union all to add the gaps from rental start to first bill
        select r.contract,r.item,rentstart,rentstop,null invoice,rentstart,dateadd("dd",-1,start.billstart)
        from @rentals r
        inner join ( -- min billstart is the first time billed
            select contract,item,min(billstart) billstart
            from @rentals
            group by contract,item
        ) start
            on start.billstart <> r.rentstart -- we don't need the ones when billing started at the same time as rent
            and start.item=r.item
            and start.contract=r.contract
    )
    order by contract,item,billstart
    

    输出:

    contract    item    rentstart   rentstop    invoice billstart   billstop
    1234        A       2019-04-01  NULL        4444    2019-04-01  2019-04-30
    1234        A       2019-04-01  NULL        4445    2019-05-01  2019-05-31
    1234        A       2019-04-01  NULL        NULL    2019-06-01  2019-06-04
    1234        A       2019-04-01  NULL        4444    2019-06-05  2019-06-30
    1234        B       2019-04-01  2019-05-15  NULL    2019-04-01  2019-04-30
    1234        B       2019-04-01  2019-05-15  4445    2019-05-01  2019-05-15
    

    【讨论】:

    • 我认为可能还需要推断它以显示任何“当前”差距。例如为“rentstop is null”添加另一个子查询,并且最后一个 billstop 是 - 例如 - 比当前日期早一个多月。基本上他们迟交了。
    猜你喜欢
    • 2018-02-06
    • 1970-01-01
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    相关资源
    最近更新 更多