如何避免此子查询并创建索引视图?
Posted
技术标签:
【中文标题】如何避免此子查询并创建索引视图?【英文标题】:How to avoid this subquery and create an indexed view? 【发布时间】:2014-09-14 10:05:03 【问题描述】:我使用 SQL Server 2008。我有下表“预测”。
Forecast_ID | Budget_Code | IAM_ID | Forecast | Timestamp
1 | 00-0001 | 24 | 123.41 | '01-01'2010'
2 | 00-0001 | 10 | 111.41 | '02-02'2010' //Is Last
3 | 00-0001 | 44 | 457.10 | '02-02'2010' //Is Last
4 | 00-0002 | 258 | 20 | '01-05'2011' //Is Last
5 | 00-0003 | 3 | 215 | '11-12'2013' //Is Last
6 | 00-0003 | 31 | 85.2 | '10-01'2010'
7 | 00-0003 | 2 | 15 | '10-01'2010'
我尝试使用每个 Budget_Code 的最后一个“预测”创建一个索引视图,即。 e.具有最高时间戳的预测(每个 Budget_Code 一行或多行)。
所以我做了以下查询:
CREATE VIEW LastForecasts
WITH SCHEMABINDING
AS
SELECT Forecast_ID, Budget_Code, IAM_ID, Forecast
FROM dbo.[Plan] p1
WHERE Timestamp = (
SELECT MAX(Timestamp)
FROM dbo.[Plan] p2
WHERE p1.Budget_Code = p2.Budget_Code)
GO
CREATE UNIQUE CLUSTERED INDEX IDX_V1
ON LastForecasts (Forecast_ID);
GO
但我有以下错误:
无法在视图“OperationPlanDB.dbo.LastForecasts”上创建索引,因为它包含一个或多个子查询。考虑将视图更改为仅使用联接而不是子查询。或者,考虑不索引此视图。
如何避免此子查询并使用最新预测索引我的视图?
【问题讨论】:
也许我错过了一些东西,但有什么理由不能索引 Timestamp 列(desc 或 asc,没关系)并覆盖其他列(Forecast_ID、Budget_Code、IAM_ID、Forecast) ,然后执行TOP WITH TIES
和ORDER BY
。
@g2server 我不认为TOP WITH TIES
可以工作(但我不是很熟悉),因为每个时间戳可以有一对多行(请参阅预算代码 00-0001我的例子)
好的,我明白了,我错过了分组。在那种情况下,我认为 medhi 的方法会起作用(但更改为 RANK() 并尝试在 Timestamp 上建立索引,用查询替换索引视图 - 如果索引设置正确,性能应该相似)。
【参考方案1】:
您不能在索引视图中使用子查询。我建议使用以下性能更好的查询而不是您的查询:
SELECT *
FROM (
SELECT Forecast_ID,
Budget_Code,
Forecast,
ROW_NUMBER() OVER (PARTITION BY Budet_Code ORDER BY Timestamp DESC) row
FROM dbo.[Plan] p1
)z
WHERE Z.row=1
【讨论】:
感谢您的回答,但我忘了说我可以有多个具有相同时间戳的预测,如果时间戳是此 Budget_Code 的最后一个,我需要获取所有预测。顺便说一句,我在示例中添加了另一列 @g2server 确实它适用于 RANK() 但我仍然无法在索引视图中使用它:/ 错误:“无法在视图“dbo.LastForecasts”上创建索引,因为它包含排名或聚合窗口函数。” 这在索引视图中不起作用,对吗?不支持派生表 (z
)。以上是关于如何避免此子查询并创建索引视图?的主要内容,如果未能解决你的问题,请参考以下文章