SQL Server IF 0,为以下日期添加值

时间:2013-09-23 21:22:08

标签: sql sql-server

我在MSSQL Server Management Studio中编写此查询,我遇到了一个精神障碍。假设我有一些建筑,当他们上线时,我想比较他们的产量与他们预测的数量,P_AMOUNT和F_AMOUNT。这是两个独立的数据库,它们组合成一个带有查询的数据库(生产数据库和预测数据库)。

enter image description here

所以这里的问题是。我想在预测每个B_ID旁边选择峰值产量。大多数建筑物都像B_ID#2并且有预测数量,但偶尔会有一个没有。就像B_ID#1一样。如果F_Amount = 0,我将如何仅向F_Date推进一个月的日期?

SELECT P1.B_ID, P1.P_DATE, P1.P_AMOUNT, F1.F_DATE, F1.F_AMOUNT
FROM DB1.Production P1
INNER JOIN DB2.Forecast F1
ON P1.DB_ID = F1.DB_ID

2 个答案:

答案 0 :(得分:0)

使用预测表的嵌套选择,以便在生产日期之后获得具有值的最小预测日期,例如:

SELECT MIN(F1.F_DATE) 
WHERE F1.F_DATE > P1.P_DATE 
    AND F1.F_AMOUNT > 0

答案 1 :(得分:0)

有几种方法可以解决您的问题。一种方法是根据F_DATE对每一行进行排名,当F_AMOUNT值为零时,拉出下一行。由于您没有指定SQL Server的版本,因此我使用了可在SQL Server 2005或更高版本中运行的语法。

With RnkItems As
    (
    Select B_ID, P_DATE, P_AMOUNT, F_DATE, F_AMOUNT 
        , Row_Number() Over ( Order By F_DATE ) As Rnk
    From SourceData
    )
Select R.B_ID, R.P_DATE, R.P_AMOUNT
    , R.F_DATE As [Original F_DATE]
    , R.F_AMOUNT As [Original F_AMOUNT]
    , Case R.F_AMOUNT
        When 0 Then R1.F_DATE
        Else R.F_DATE
        End As F_DATE
    , Case R.F_AMOUNT
        When 0 Then R1.F_AMOUNT
        Else R.F_AMOUNT
        End As F_AMOUNT
From RnkItems As R
    Left Join RnkItems As R1
        On R1.Rnk = R.Rnk + 1

SQL Fiddle Version

如果您使用的是SQL Server 2012,则可以使用新的Lead功能:

Select B_ID, P_DATE, P_AMOUNT
    , F_DATE As [Original F_DATE]
    , F_AMOUNT As [Original F_AMOUNT]
    , Case F_AMOUNT 
        When 0 Then Lead ( F_DATE, 1 ) Over ( Order By F_DATE )
        Else F_DATE
        End As F_DATE
    , Case F_AMOUNT 
        When 0 Then Lead ( F_AMOUNT, 1 ) Over ( Order By F_DATE )
        Else F_AMOUNT
        End As F_AMOUNT
From SourceData

SQL Fiddle Version

以上两种解决方案依赖于规定的要求,即您总是要提前一个月。但是,如果您希望第一个月具有非零值(即,它可能是多次跳转),那就不同了:

Select S.B_ID, S.P_DATE, S.P_AMOUNT
    , S.F_DATE As [Original F_DATE]
    , S.F_AMOUNT As [Original F_AMOUNT]
    , Case S.F_AMOUNT
        When 0 Then (
                    Select Min( S2.F_DATE )
                    From SourceData As S2
                    Where S2.F_DATE >= S.F_DATE
                        And S2.F_AMOUNT <> 0
                    )
        Else S.F_DATE
        End As F_DATE
    , Case S.F_AMOUNT
        When 0 Then (
                    Select S1.F_AMOUNT
                    From SourceData As S1
                    Where S1.F_DATE =   (
                                        Select Min( S2.F_DATE )
                                        From SourceData As S2
                                        Where S2.F_DATE > S.F_DATE
                                            And S2.F_AMOUNT <> 0
                                        )
                    )
        Else S.F_AMOUNT
        End As F_AMOUNT
From SourceData As S

SQL Fiddle Version