加入CTE转换表

时间:2011-02-18 16:59:36

标签: sql sql-server-2008 tsql common-table-expression indexed-views

我经常会遇到这样的情况,我需要将一张大桌加入到桌子的某个转换中。

我用一张大桌子和一张较小的价格表做了一个例子。

输入表CarPrices,其中包含每个汽车品牌/型号的价格,包括起始日期和结束日期。我想将所有售出的汽车加入CarPrices表中的销售价格,在SaleDate BETWEEN PriceStartingDate和PriceEndingDate的标准上,但如果期间没有价格,我想加入找到的最新价格。

我可以像这样完成它,但速度非常慢:

WITH CarPricesTransformation AS (
    SELECT CarBrand, CarModel, PriceStartingDate,
        CASE WHEN row_number() OVER (PARTITION BY CarBrand, CarModel, 
            ORDER BY PriceStartingDate DESC) = 1
            THEN NULL ELSE PriceEndingDate END PriceEndingDate,
        Price
    FROM CarPrices
)
SELECT SUM(Price)
FROM LargeCarDataBase C
INNER JOIN CarPricesTransformation P
ON C.CarBrand = P.CarBrand
AND C.CarModel = P.CarModel
AND C.SaleDate >= P.PriceStartingDate
AND (C.SaleDate <= P.PriceEndingDate OR P.PriceEndingDate IS NULL)

更快地执行此操作的一种可靠方法是忘记创建VIEW并创建存储过程,我首先将较小价格表作为具有正确聚簇索引的临时表进行准备,然后将其连接到该表。这要快得多。但我想坚持一个观点。

有什么想法......?

2 个答案:

答案 0 :(得分:0)

由于价格取决于销售日期,因此您无法制作“较小价格表”。另外,为什么CTE首先出现?

Select
  Sum(Coalesce(ActivePrice.Price, LatestPrice.Price))
From
  LargeCarDataBase As Sales
  Left Outer Join CarPrices As ActivePrice
    On Sales.CarBrand = ActivePrice.CarBrand
    And Sales.CarModel = ActivePrice.CarModel
    And (((Sales.SaleDate >= ActivePrice.PriceStartingDate)
          And ((Sales.SaleDate <= ActivePrice.PriceEndingDate)
               Or (ActivePrice.PriceEndingDate Is Null)))
  Left Outer Join CarPrices As LatestPrice
    On Sales.CarBrand = LatestPrice.CarBrand
    And Sales.CarModel = LatestPrice.CarModel
    And LatestPrice.PriceEndingDate Is Null

答案 1 :(得分:0)

您是否尝试过Indexed Views

索引视图的结果会自动提交到磁盘,因此您可以超快速地检索它们。

    CREATE VIEW [dbo].[SuperFastCarPrices] WITH SCHEMABINDING AS
    SELECT  C.CarBrand,
            C.CarModel,
            C.SaleDate,
            SUM(P.Price) AS Price
    FROM CarPrices P
    INNER JOIN LargeCarDataBase C
        ON C.CarBrand = P.CarBrand
        AND C.CarModel = P.CarModel
        AND C.SaleDate >= P.PriceStartingDate
        AND (P.PriceEndingDate IS NULL OR C.SaleDate <= P.PriceEndingDate)
    GROUP BY C.CarBrand, C.CarModel, C.SaleDate

    CREATE UNIQUE CLUSTERED INDEX [IDX_SuperFastCarPrices] 
    ON [dbo].[SuperFastCarPrices](CarBrand, CarModel, SaleDate)

然后,您可以直接从此视图中选择,该视图将以与从表格中选择的速度相同的速度返回记录。

索引视图减慢了对基础表的更改的缺点。如果您担心在创建此视图后将记录插入表LargeCarDataBase的成本,您可以在列CarBrand,CarModel和SaleDate上创建索引,这将加快此表的插入和更新。

有关索引视图的更多信息,请参阅Microsoft's Article