Sql 连接到表的CTE转换
我经常遇到这样的情况,需要将一个大表连接到表的某个转换 我用一张大桌子和一张小价格桌子做了一个例子 输入CarPrices表,该表包含每个汽车品牌/型号的价格以及开始和结束日期。我想在PriceStartingDate和PriceEndingDate之间的Criteriam SaleDate上将所有售出的汽车与Carprice表中的销售价格合并,但如果在此期间没有价格,我想与找到的最新价格合并 我可以这样完成,但速度非常慢:Sql 连接到表的CTE转换,sql,sql-server-2008,tsql,common-table-expression,indexed-views,Sql,Sql Server 2008,Tsql,Common Table Expression,Indexed Views,我经常遇到这样的情况,需要将一个大表连接到表的某个转换 我用一张大桌子和一张小价格桌子做了一个例子 输入CarPrices表,该表包含每个汽车品牌/型号的价格以及开始和结束日期。我想在PriceStartingDate和PriceEndingDate之间的Criteriam SaleDate上将所有售出的汽车与Carprice表中的销售价格合并,但如果在此期间没有价格,我想与找到的最新价格合并 我可以这样完成,但速度非常慢: WITH CarPricesTransformation AS (
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)
一种可靠的快速实现方法是忘记创建视图和创建存储过程,首先将较小的prices表准备为具有正确聚集索引的临时表,然后将其连接到该表。这要快得多。但我想坚持一种观点
有什么想法吗?你不能制作一个更小的价格表,因为价格取决于销售日期。还有,为什么要把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
你不能做一个更小的价格表,因为价格取决于销售日期。还有,为什么要把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
你试过了吗
索引视图的结果会自动提交到磁盘,因此您可以超快速地检索它们
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)
然后,您可以直接从此视图中进行选择,该视图将以与从表中选择相同的速度返回记录
有一个缺点是索引视图会减慢对基础表的更改。如果您担心在创建此视图后将记录插入表LargeCardDatabase的成本,则可以在CarBrand、CarModel和SaleDate列上创建索引,这将加快此表的插入和更新速度
有关索引视图的详细信息,请参见 你试过了吗
索引视图的结果会自动提交到磁盘,因此您可以超快速地检索它们
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)
然后,您可以直接从此视图中进行选择,该视图将以与从表中选择相同的速度返回记录
有一个缺点是索引视图会减慢对基础表的更改。如果您担心在创建此视图后将记录插入表LargeCardDatabase的成本,则可以在CarBrand、CarModel和SaleDate列上创建索引,这将加快此表的插入和更新速度
有关索引视图的详细信息,请参见 看看您是否希望中间结果具体化和索引您最好使用临时表来明确执行此操作,尽管答案中的链接给出了使用计划指南执行此操作的示例。我很困惑,您使用的视图的名称是什么?看起来您可能正在交替使用CTE/View。这是一个你应该打破的习惯,因为它们不是一回事。你的执行计划是怎么说的?这可能通过添加/修改表上的索引来解决…@Abe。我认为问题中的代码是视图定义。创建视图foo,因为您是否有一些指标可以使用?大型CardDatabase中的记录数量?CarpriceTransformation中的记录?平均每辆车的价格等?看看你是否想要中间结果具体化和索引。你最好明确使用临时表来实现这一点,尽管答案中的链接给出了使用计划指南来实现这一点的示例。我很困惑,你使用的视图的名称是什么?看起来您可能正在交替使用CTE/View。这是一个你应该打破的习惯,因为它们不是一回事。你的执行计划是怎么说的?这可能通过添加/修改表上的索引来解决…@Abe。我认为问题中的代码是视图定义。创建视图foo,因为您是否有一些指标可以使用?大型CardDatabase中的记录数量?CarpriceTransformation中的记录?每辆车的平均价格等?