SQL Server 2005中的“类似CSS”的后备级联数据

时间:2009-04-14 16:51:15

标签: sql sql-server

我正在尝试在SQL Server中实现价格回退系统。我想为产品定义一套越来越具体的价格(例如:按地区,商店,仓库等),可能会或可能不会定义,并且能够选择最具体的价格(即:报告中定义了大多数参数的一个。

例如,我可能有以下数据:

 Region
--------
   1
   2

 Store  
--------
   1
   2
   3

Product | Region | Store | Price
--------------------------------
  Foo   | NULL   | NULL  |  1.0
  Foo   | 1      | NULL  |  2.0
  Foo   | 1      | 1     |  2.5
  Foo   | 1      | 2     |  2.3

所以如果我想知道产品Foo的价格......

  • 在1区,商店1 = 2.5
  • 区域1中的
  • ,存储3 = 2.0 (存储3未在数据中明确定义,因此结果来自区域1的NULL存储)
  • 区域2中的
  • ,Store 4 = 1.0 (区域2未在数据中明确定义,因此结果来自NULL区域)

为了简单起见,我可以假设商店总是比区域更具体,商店只能存在于一个地区。

此数据的架构如下:

CREATE TABLE Prices(
    ID      int   IDENTITY(1,1) NOT NULL,
    Product int   NOT NULL,
    Region  int   NULL,
    Store   int   NULL,
    Price   money NOT NULL,
    CONSTRAINT PK_Prices PRIMARY KEY CLUSTERED (ID ASC),
    CONSTRAINT IX_Prices UNIQUE NONCLUSTERED (Product ASC, Region ASC, Store ASC)
)

除了在代码中处理这些数据之外,如何根据(地区,商店)查询此表以获取每种产品的有效价格列表?

4 个答案:

答案 0 :(得分:4)

试试这个:
所有产品的 EDIT ,每个产品都列出一次,即使给定的地区和商店不存在......

CREATE PROCEDURE GetPrice
     @Region int = null
    ,@Store int = null
AS

SELECT
    Product
        ,Region
        ,Store
        ,Price
    FROM (SELECT
              Product
                  ,Region AS Region
                  ,Store As Store
                  ,Price
                  ,Row_Number() OVER(PARTITION BY Product ORDER BY SortBy,Product,Region,Store,Price) AS RowNumber
              FROM (SELECT 1 AS SortBy,* FROM Prices WHERE (Region = @Region OR @Region IS NULL) AND (Store = @Store OR @Store IS NULL)
                    UNION
                    SELECT 2 AS SortBy,* FROM Prices WHERE (Region = @Region OR @Region IS NULL) 
                    UNION
                    SELECT 3 AS SortBy,* FROM Prices
                   ) Prices
         ) dt
    WHERE RowNumber=1
    ORDER BY Product

GO

答案 1 :(得分:2)

哇,你们这些人都在努力。这是一个简单的方法:使用COALESCE命令,它获取第一个非空值。

SELECT COALESCE(st.Price, rg.Price, gn.Price) AS Price
  FROM dbo.Prices gn  /*General price*/
  LEFT OUTER JOIN dbo.Prices rg /*Regional price*/
    ON rg.Product = @Product AND rg.Region = @Region AND rg.Store IS NULL
  LEFT OUTER JOIN dbo.Prices st  /*Store price*/
    ON rg.Product = @Product AND rg.Region = @Region AND rg.Store = @Store
  WHERE gn.Product = @Product
    AND gn.Region IS NULL AND gn.Store IS NULL

这样,如果不是空的话,您将获得商店价格,如果不是空的话,您将获得区域价格,如果所有其他商品都失败,您将获得一般价格。

答案 2 :(得分:1)

我认为您的数据模型可能有点棘手。价格表是否仅为报告填充?我可能会查看我的表格,但如果我必须使用此设置,我会做这样的事情:

指定区域内的产品价格(非商店)。在接受区域作为参数的sproc中使用此选择。如果我做得对,它将返回区域价格(如果有的话)和产品价格(如果没有)。

选择产品,价格来自dbo.prices,其中(Region = @ region)或(区域为NULL且产品不在(从区域= @Region的价格中选择产品))

指定商店的产品价格。在接受存储作为参数的存储区中使用此选择。您还需要传入区域或从商店中找出它。如果我做得对,它将返回商店价格,如果有,那么他区域价格,然后是产品价格。

选择产品,价格来自dbo.prices,其中(store = @store)或(商店为NULL AND region = @Region且产品不在(从商店= @store的价格中选择产品)或(商店为NULL和区域)是NULL并且产品不在(从region = @Region的价格中选择产品))

要从多个地区或商店获取价格,只需多次执行上述某个sprocs(在循环或游标中)。

答案 3 :(得分:-1)

我想这一定必须有效(尽管没有试过):

select top 1 price
from prices
where product = @product
and isnull(region, @region) = @region
and isnull(store, @store) = @store
order by region desc, store desc

产品必须至少有1个价格记录。 ORDER BY .. DESC最后对原始NULL值进行排序。