2

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

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

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

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

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 并创建存储过程,我首先将较小的价格表准备为具有正确聚集索引的临时表,然后对其进行连接。这要快得多。但我想坚持一个观点。

有什么想法吗...?

4

2 回答 2

0

您是否尝试过索引视图

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

    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 的文章

于 2011-04-06T16:06:21.680 回答
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
于 2011-03-01T21:38:13.083 回答