C#比较日期范围

时间:2012-07-20 14:04:54

标签: c# .net sql linq

需要一些严重的脑力!我有一个问题,我试图从两个给定的日期范围计算价格过度收费。基本上我有一个发票行如下:

BillID     AccountID     BilledFrom        BillTo      Price
 34         3456         10/10/2012       10/12/2012    86p 

然后我有一个定价矩阵,可以是:

AccountID      EffectiveFrom       EffectiveTo     Price
 3456          09/09/2009          10/11/2012      86p
 3456          11/11/2012          20/11/2012      56p
 3456          21/11/2012          10/12/2013      24p
 3456          11/12/2013           null           18p -- null never expires

目前初始价格是在BillFrom日期介于EffectiveFrom和EffectiveTo日期之间并按天计费的。现在我想从账单中计算出多收费用,因为您可以看到BillTo日期超过了86p线的EffectiveTo日期。所以有一个月的时间,客户被超额收费作为第2行或定价应该开始。我需要一个SQL或C#的功能,这将导致结果:

OverchargeID    type      BillID       Reason       Days     Price
    1          Credit      34       PriceChange      10        36p       (86p-56p)
    2          Credit      34       PriceChange      19        64p       (86p-24p)

我将处理56000条记录,最多可能有10个价格范围。我有以下代码在服务器端工作,但它根本不实用,大约需要10分钟。对此代码的任何解决方案或修改都将不胜感激。

foreach (InvoiceOverchargePriceChange_SelectResult line in result) {

            //Get the invoiceLineRecord
            InvoiceLine invoiceLine = _dataContext.InvoiceLines.Where(m=>m.InvoiceLineID == line.InvoiceLineID).FirstOrDefault();


            // get the prices for each line
            List<Pricing_SelectResult> prices = ctrl.Select(line.AccountID, null, null, null, null)
                                                    .Where(m=>m.BillingMethodID == line.BillingMethodID)
                                                    .OrderByDescending(m=>m.EffectiveFrom).ToList();

            // if the price count is greater than 1 then need to check if overcharges occurred
            if (prices.Count > 1) {

                DateTime date = new DateTime();
                int days = 0;
                decimal charge = 0; ;
                for (int i = 0; i < prices.Count(); i++) {
                    days = 0;
                    charge = 0;

                    //if it goes in we found our price that we used
                    if (invoiceLine.BillFrom >= prices[i].EffectiveFrom && prices[i].EffectiveTo != null) {

                        date = invoiceLine.BillTo;
                        if (prices[i].EffectiveTo == null) break;
                        //check the Bill to date does not exceed the effective To date, if it does go in
                        while (date >= prices[i].EffectiveTo) {



                            if (date == invoiceLine.BillTo) {

                                //if its first go set the price
                                charge = prices.Where(m => date >= m.EffectiveFrom).FirstOrDefault().Price;


                            }

                            if (charge == prices.Where(m => date >= m.EffectiveFrom).FirstOrDefault().Price) {

                                //increment the days counter
                                days++;
                                date = date.AddDays(-1);

                            }
                            else {

                                //insert the days and price into db here...


                                //reset the days
                                days = 0;
                                charge = prices.Where(m => date >= m.EffectiveFrom).FirstOrDefault().Price;




                            }


                        }

                    }

                }

            }


        }

提前致谢

1 个答案:

答案 0 :(得分:0)

试试这个......

 select 
      ROW_NUMBER() over (order by BillID, StartDate),
      case when (billprice>pricingprice) then 'Credit' else 'Debit' end,
      BillID,
      DATEDIFF(d, startdate,enddate)+1 as days,
      billprice-pricingprice
 from
 (
      select 
           BillID, 
           case when Effectivefrom>BilledFrom then Effectivefrom else BilledFrom end startdate, 
           case when isnull(effectiveto,GETDATE())<BillTo 
                then isnull(effectiveto,GETDATE()) else billto-1 end enddate,
           bill.price as billprice,
           pricing.price as pricingprice
      from pricing
     inner join bill
                on bill.accountid= pricing.accountid 
                and (billedfrom<isnull(effectiveto,getdate())) and (BillTo>Effectivefrom)
                and bill.price <> pricing.price 
 ) v