循环选择以计算每个月的值

时间:2015-03-26 09:22:39

标签: sql sql-server-2008

我的存储过程有4个参数:startdate,enddate,allocationID&语言。对我的问题真正重要的是日期。

使用这些参数,存储过程将从不同的表中收集汽车日期并返回包含每个月的空记录的选择,并且每月每辆汽车的填充记录在汽车具有有效里程值的情况下。因此,如果日期是'2008-01-01'和' 2008-06-01'这是一个示例结果。

enter image description here

在示例中,第一辆车具有所有月份的值,但第二辆车在第一个月缺失。我现在需要做的是添加逻辑,以便选择中的每辆车每个月都有一行。然后我必须通过获取前一个和下一个里程值来计算该月的里程值。

我知道如何在C#中执行此操作,但我不熟悉SQL。我的问题是如何迭代几个月,然后再次通过carID迭代并检查它们是否有里程值。

我知道我必须制作一个临时表,但我不知道如何只用一段时间和一个案例来做这件事。

编辑:这是我用来测试的查询,与程序

具有相同的代码
--DECLARATION VARS
    DECLARE @Taal varchar(5) = 'en-us'
    DECLARE @VanDate datetime = '2008-01-01'
    DECLARE @TotDate datetime = '2008-06-01'
    DECLARE @AllocationID AS uniqueidentifier = 'BD83AEDE-6DFB-4DF5-9F18-C373D6A468D1'

    DECLARE @TaalID int 
    DECLARE @Months int
    DECLARE @FirstDay AS DateTime
    DECLARE @LastDay AS Datetime

    DECLARE @DefaultFirstDay as Datetime
    DECLARE @DefaultLastDay as Datetime

    DECLARE @ControlDay AS datetime

    --DEFAULT MONTHS SPAN
    SET @Months = 18   

    SELECT @TaalID = MIN(eMK_Languages.ID) 
    FROM eMK_Languages WHERE LEFT(eMK_Languages.LangCode,2) = LEFT (@Taal,2)

    Set @Lastday = ISNULL(@TotDate,dateadd(dd,0,datediff(dd,0,{fn NOW()})));
    --select @Lastday as Lastday;
    Set @Firstday = ISNULL(@VanDate, 
    DATEADD(dd,-(DAY(DATEADD(mm, -(1-@Months) , @LastDay))-1),DATEADD(mm, 1 -(@Months) , @LastDay)));
    --select @Firstday as Firstday;
    SET @ControlDay = dateadd(dd,0, datediff(dd,0,@LastDay));

;WITH 

MonthList (MonthDate) AS -- lijst van maanden
(   
SELECT 
    DATEADD(dd,-(DAY(DATEADD(mm, 0 , @LastDay))-1),DATEADD(mm, 0 , @LastDay))
    UNION ALL
    SELECT DATEADD(mm, -1, MonthDate) 
        FROM MonthList
    WHERE (MonthDate > @FirstDay)
),

AllocationList AS 
(
    SELECT  COST.CostAllocationID, 
            COST.Name as AllocationName
    FROM    eMK_CostAllocation AS COST
    WHERE (COST.CostAllocationID = @AllocationID OR @AllocationID IS NULL)
            AND (COST.StartDate <= @LastDay OR COST.StartDate IS NULL) 
            AND (COST.EndDate IS NULL OR COST.EndDate >= @FirstDay)
    UNION ALL
    SELECT NULL,NULL
)  
,
AllocationCrossList AS 
(
    SELECT  ML.MonthDate,
            DATEADD(dd,-1,DATEADD(mm,1,ML.MonthDate)) as endmonth,
            ML.MonthDate as  X_AXIS,
            DATEADD(dd,-1,DATEADD(mm,1,ML.MonthDate)) X_AXIS_2,
            AL.CostAllocationID,
            AL.AllocationName
    FROM MonthList AS ML
    CROSS JOIN AllocationList AS AL
)  
,CarList AS 
(   
    SELECT 
    M.MonthDate as beginmonth
,   DATEADD(dd,-1,DATEADD(mm,1,M.MonthDate)) as endmonth
,   M.MonthDate as  X_AXIS
,   DATEADD(dd,-1,DATEADD(mm,1,M.MonthDate)) X_AXIS_2
,   C.CarID 
--, (dbo.fGetAllocationNameFromDate(C.CarID,DATEADD(dd,-1,DATEADD(mm,1,M.MonthDate)))) as AllocationName
,   dbo.fGetAllocationFromDate(C.CarID,DATEADD(dd,-1,DATEADD(mm,1,M.MonthDate))) as AllocationID
,   C.StartDate
,   C.FinalEndDate
,   dbo.fGetTranslation(C.CarTypeID,@TaalID) as Nature
,   C.BuiltYear
,   VHC.Co2Emission

FROM
    eMK_Car C
    CROSS JOIN MonthList M 
    CROSS JOIN eMK_Vehicle VHC

 WHERE 
    (
    C.StartDate <= DATEADD(dd,-1,DATEADD(mm,1,M.MonthDate))
    AND (C.FinalEndDate IS NULL OR C.FinalEndDate >= M.MonthDate )
    AND C.VehicleID = VHC.VehicleID
    ) 
)       


, unionlist as (SELECT 
    'Fuelcard' as oorsprong
,   CAR.beginmonth
,   CAR.endmonth
,   CAR.X_AXIS
,   CAR.CarID 
,   CAR.AllocationID
,   (CASE   WHEN CAR.CarID IS NULL 
            THEN 'N'
            ELSE 'Y'
            END ) as ValidData
,   CAR.Co2Emission
,   fuelcardrefill.Kilometer as kilometerstand
,   fuelcardrefill.FK_FuelType
,   fuelcardrefill.Date as datum

From    CarList AS CAR inner join
        dbo.eMK_CarFuelCard as carfuelcard On CAR.CarID = carfuelcard.CarID inner join
        dbo.eMK_FuelCard as fuelcard on carfuelcard.FuelCardID = fuelcard.ID inner join 
        dbo.eMK_FuelCard_Refill as fuelcardrefill on fuelcard.ID = fuelcardrefill.FK_FuelCard

Where 
      (fuelcardrefill.Date >= CAR.beginmonth and fuelcardrefill.Date <= CAR.endmonth)

UNION

SELECT 
    'Costs' as oorsprong
,   CAR.beginmonth
,   CAR.endmonth
,   CAR.X_AXIS
,   CAR.CarID 
,   CAR.AllocationID
,   (CASE   WHEN CAR.CarID IS NULL 
            THEN 'N'
            ELSE 'Y'
            END ) as ValidData
,   CAR.Co2Emission
,   COSTS.Mileage as kilometerstand
,   NULL
,   COSTS.DateInvoice as datum

FROM
    CarList AS CAR inner join
    dbo.Emk_Cost as COSTS on CAR.CarID = COSTS.CarID 

Where 
      (COSTS.CostDate > beginmonth and COSTS.CostDate < endmonth)

UNION

SELECT 
    'Caruse_start' as oorsprong
,   CAR.beginmonth
,   CAR.endmonth
,   CAR.X_AXIS
,   CAR.CarID 
,   CAR.AllocationID
,   (CASE   WHEN CAR.CarID IS NULL 
            THEN 'N'
            ELSE 'Y'
            END ) as ValidData
,   CAR.Co2Emission
,   CARUSE.MileageStart as kilometerstand
,   NULL
,   CARUSE.StartDate as datum

FROM
    CarList AS CAR inner join
    dbo.eMK_CarUse as CARUSE on CARUSE.CarID = CAR.CarID

Where 
      (CARUSE.StartDate >= beginmonth and CARUSE.StartDate <= endmonth)


UNION

SELECT 
    'Caruse_end' as oorsprong
,   CAR.beginmonth
,   CAR.endmonth
,   CAR.X_AXIS
,   CAR.CarID 
,   CAR.AllocationID
,   (CASE   WHEN CAR.CarID IS NULL 
            THEN 'N'
            ELSE 'Y'
            END ) as ValidData
,   CAR.Co2Emission
,   CARUSE.MileageEnd as kilometerstand
,   NULL
,   CARUSE.EndDate as datum

FROM
    CarList AS CAR inner join
    dbo.eMK_CarUse as CARUSE on CARUSE.CarID = CAR.CarID

Where 
      (CARUSE.EndDate >= beginmonth and CARUSE.EndDate <= endmonth)


UNION

SELECT 
    'AllocationCross' as oorsprong
,   AL.MonthDate as beginmonth
,   AL.endmonth
,   AL.X_AXIS
,   NULL as CarID 
,   AL.CostAllocationID
,   'N' as ValidData
,   NULL
,   NULL
,   NULL
,   NULL

From    AllocationCrossList as AL)

, resultunionlist as (
SELECT 
        UL1.*,
        CASE WHEN EXISTS(
            SELECT * 
            FROM unionlist AS UL2
            WHERE
                UL2.CarID = UL1.CarID AND
                UL2.datum < UL1.datum AND
                UL2.kilometerstand < UL1.kilometerstand OR
                UL1.oorsprong = 'Caruse_start'
        )
        THEN 'Y'
        ELSE 'N'
        END AS validkmstand
FROM unionlist as UL1)

, totalmileagelist as (
SELECT
    'Fuelcard' as oorsprong
,   CAR.CarID 
,   (CASE   WHEN CAR.CarID IS NULL 
            THEN 'N'
            ELSE 'Y'
            END ) as ValidData
,   CAR.Co2Emission
,   fuelcardrefill.Kilometer as kilometerstand
,   fuelcardrefill.FK_FuelType
,   fuelcardrefill.Date as datum

From    CarList AS CAR inner join

        dbo.eMK_CarFuelCard as carfuelcard On CAR.CarID = carfuelcard.CarID inner join
        dbo.eMK_FuelCard as fuelcard on carfuelcard.FuelCardID = fuelcard.ID inner join 
        dbo.eMK_FuelCard_Refill as fuelcardrefill on fuelcard.ID = fuelcardrefill.FK_FuelCard

Where 
      (fuelcardrefill.Date < @VanDate )

      UNION

SELECT 
    'Caruse_start' as oorsprong
,   CAR.CarID 
,   (CASE   WHEN CAR.CarID IS NULL 
            THEN 'N'
            ELSE 'Y'
            END ) as ValidData
,   CAR.Co2Emission
,   CARUSE.MileageStart as kilometerstand
,   NULL
,   CARUSE.StartDate as datum

FROM
    CarList AS CAR inner join
    dbo.eMK_CarUse as CARUSE on CARUSE.CarID = CAR.CarID

Where 
      (CARUSE.StartDate < @VanDate)
)

,   resultlist as (
SELECT
    CarID
,   '01/01/2000' as beginmonth
,   NULL as X_AXIS
,   MAX(kilometerstand) as Kilometers
,   MAX(Co2Emission) as CO2

FROM
    totalmileagelist
GROUP BY CarID

UNION

SELECT
    CarID
,   beginmonth
,   X_AXIS
,   MAX(kilometerstand) as Kilometers
,   MAX(Co2Emission) as CO2

FROM
resultunionlist
GROUP BY CarID, beginmonth, X_AXIS
)

,   withoutprevalueslist as (
select ml.*,
       (ml.Kilometers - mlprev.Kilometers) as diff
from resultlist ml outer apply
     (select top 1 ml2.*
      from resultlist ml2
      where ml2.CarId = ml.CarId and
            ml2.beginmonth < ml.beginmonth
      order by ml2.beginmonth desc
     ) mlprev
)


SELECT *
FROM withoutprevalueslist
WHERE beginmonth >= @VanDate

option (MAXRECURSION 999)

0 个答案:

没有答案