2

大きなテーブルをテーブルの特定の変換に結合する必要がある、このような状況に頻繁に遭遇します。

大きなテーブルと小さな価格テーブルの例を作成しました。

テーブル CarPrices を入力します。これには、自動車のブランド/モデルごとの価格と、開始日および終了日が含まれています。PriceStartingDate と PriceEndingDate の間の基準 SaleDate で、すべての販売車を CarPrices テーブルの販売価格に結合したいのですが、その期間の価格がない場合は、見つかった最新の価格に結合したいと考えています。

私はこのようにそれを達成することができますが、それは非常に遅いです:

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

価格は発売日によって異なるため、「より小さな価格表」を作成することはできません。また、そもそもなぜ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 に答える
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 に答える