【问题标题】:Joining to CTE transformation of table加入表的 CTE 转换
【发布时间】:2023-03-19 19:36:02
【问题描述】:

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

我做了一个大表和小价格表的例子。

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

有什么想法吗...?

【问题讨论】:

  • 请参阅Quassnoi's answer here 如果您希望中间结果具体化和索引,最好使用#temp 表显式执行此操作,尽管答案中的链接提供了使用计划执行此操作的示例指导。
  • 我很困惑,您使用的视图名称是什么?看起来您可能正在交替使用 CTE/View。这是一个你应该改掉的习惯,因为它们不是一回事。
  • 你的执行计划是怎么说的?这可以通过添加/修改表上的索引来解决...
  • @Abe。我认为问题中的代码是视图定义。 CREATE VIEW foo AS &lt;op's code goes here&gt;
  • 您有一些指标可以使用吗? LargeCarDataBase 中的记录数? CarPricesTransformation 中的记录数?每辆车的平均价格等?

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


【解决方案1】:

您不能制作“较小的价格表”,因为价格取决于销售日期。另外,为什么首先是 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

【讨论】:

    【解决方案2】:

    你试过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

    【讨论】:

      猜你喜欢
      • 2022-06-15
      • 2012-04-25
      • 2021-03-24
      • 1970-01-01
      • 1970-01-01
      • 2020-06-08
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      相关资源
      最近更新 更多