根据输入的单位计算价格

时间:2016-08-05 16:47:47

标签: sql-server-2012 sql-server-2008-r2 sql-server-2014

表架构:

CREATE TABLE [dbo].[TblPriceDetails](
    [PriceID] [int] IDENTITY(1,1) NOT NULL,
    [VID] [int] NOT NULL,
    TypeID int not null,
    [RangeStart] [decimal](18, 3) NOT NULL,
    [RangeEnd] [decimal](18, 3) NOT NULL,
    [Price] [decimal](18, 2) NOT NULL,
    [ExtraLoad] [decimal](18, 3) NULL,
    [ExtraPrice] [decimal](18, 2) NULL
)
GO

示例数据

Insert into dbo.TblPriceDetails values (1,1, 0,0.250,10,0,0)
Insert into dbo.TblPriceDetails values (1,1, 0.251,0.500,15,0.500,15)
Insert into dbo.TblPriceDetails values (1,1, 3,5,40,1,25)
GO
Insert into dbo.TblPriceDetails values (1,2, 0,0.250,15,0,0)
Insert into dbo.TblPriceDetails values (1,2, 0.251,0.500,20,0.500,20)
Insert into dbo.TblPriceDetails values (1,2, 3,5,50,1,30)
GO

预期输出:

对于VID = 1和TypeID = 1且给定值 0.300

  • 由于输入单位介于RangeStart 0.251和RangeEnd 0.500之间 结果价格为15

对于VID = 1和TypeID = 1且给定值 0.600

  • 根据数据直到0.500,价格为15,每增加一次 高达0.500另一个15.所以最终价格将是30

对于VID = 1和TypeID = 1且给定值 1.500

  • 根据数据直到0.500,价格为15.每增加0.500 它的另外15个,所以对于剩下的1个单位,它将是15 * 2 最终价格为45

对于VID = 1和TypeID = 1且给定值 5.5

  • 根据数据直到5.000,价格为40.每增加1个单位,另外25个,所以最终价格为65

在为此编写查询时需要帮助。与我的其他问题不同,我还没有查询到现在我想出的问题。截至目前,我无法构建逻辑并为此提出通用查询。

1 个答案:

答案 0 :(得分:1)

看起来您正在考虑计算邮资价格。诀窍是加入下一个权重层的RangeStartLEAD将帮助您实现这一目标:

;WITH
    AdjustedPriceDetails AS
    (
        SELECT      VID, TypeID, RangeStart, RangeEnd, Price, ExtraLoad, ExtraPrice
                ,   ISNULL(LEAD(RangeStart, 1) OVER (PARTITION BY VID, TypeID ORDER BY RangeStart), 1000000) AS NextRangeStart
        FROM        TblPriceDetails
    )


SELECT      T.*
        ,   A.Price + IIF(T.Value <= A.RangeEnd, 0, CEILING((T.Value - A.RangeEnd) / A.ExtraLoad) * A.ExtraPrice)
                                            AS FinalPrice
FROM        #TestData               T
INNER JOIN  AdjustedPriceDetails    A       ON A.RangeStart <= T.Value AND T.Value < A.NextRangeStart

说明:

  • LEAD(RangeStart, 1) OVER (PARTITION BY VID, TypeID ORDER BY RangeStart)获取具有相同RangeStartVID
  • 的下一行的TypeID
  • 您最终将达到最高等级。因此ISNULL(..., 1000000)使此层看起来以1M结尾。 1M只是无限的替身。

编辑:如果您想使用SQL Server 2008,请更改CTE:

;WITH
    tmp AS
    (
        SELECT      VID, TypeID, RangeStart, RangeEnd, Price, ExtraLoad, ExtraPrice
                ,   ROW_NUMBER() OVER (PARTITION BY VID, TypeID ORDER BY RangeStart) AS RowNumber
        FROM        TblPriceDetails
    ),
    AdjustedPriceDetails AS
    (
        SELECT      T1.VID, T1.TypeID, T1.RangeStart, T1.RangeEnd, T1.Price, T1.ExtraLoad, T1.ExtraPrice
                ,   ISNULL(T2.RangeStart, 1000000) AS NextRangeStart
        FROM        tmp     T1
        LEFT JOIN   tmp     T2  ON T1.VID = T2.VID AND T1.TypeId = T2.TypeID AND T1.RowNumber + 1 = T2.RowNumber
    )

如果你想知道#TestData是什么(你可能不需要它)

CREATE TABLE #TestData
(
        VID         int
,       TypeID      int
,       Value       float
)

INSERT INTO #TestData
            ( VID, TypeID, Value)
    VALUES  ( 1, 1, 0.3 )
        ,   ( 1, 1, 0.6 )
        ,   ( 1, 1, 1.5 )
        ,   ( 1, 1, 5.5 )