Sql 视图中的窗口函数用“调用”;其中;给出了错误的执行计划

Sql 视图中的窗口函数用“调用”;其中;给出了错误的执行计划,sql,sql-server,Sql,Sql Server,我有一个使用滞后的观点 CREATE VIEW V_ImportedReadingDay2 AS SELECT ID, PlacementID, LAG(Reading, 1) OVER (PARTITION BY MeterNumber ORDER BY Date) AS Val FROM dbo.ImportedReadingDay 如果我使用“WHERE”调用它,它得到的执行计划比只调用查询要糟糕得多 SELECT ID, PlacementID,

我有一个使用滞后的观点

CREATE VIEW V_ImportedReadingDay2
AS
SELECT
    ID,
    PlacementID,
    LAG(Reading, 1) OVER (PARTITION BY MeterNumber ORDER BY Date) AS Val
FROM dbo.ImportedReadingDay
如果我使用“WHERE”调用它,它得到的执行计划比只调用查询要糟糕得多

SELECT
    ID,
    PlacementID,
    LAG(Reading, 1) OVER (PARTITION BY MeterNumber ORDER BY Date) AS Val
FROM dbo.ImportedReadingDay
WHERE (PlacementID = 12404)

SELECT *
FROM V_ImportedReadingDay2
WHERE (PlacementID = 12404)

这是一个已知的问题。你可以用谷歌搜索这个问题。 我找到了两种解决办法。使用表值函数或将滞后移到视图之外


但我想知道是否还有其他解决方案,因为我必须在客户端软件中使用视图,所以这些解决方案对我都不起作用。

这是一个简化视图,仅用于此示例。 在真实的一个我划分滞后。
我发现,使用“WHERE”(在本例中为PlacementID)中使用的相同方法对延迟进行分区,解决了性能问题。

仅针对本例,这是一个简化视图。 在真实的一个我划分滞后。
我发现用“WHERE”(在本例中为PlacementID)中使用的相同方法对延迟进行分区解决了性能问题。

您的两个查询在逻辑上并不相同。所以,当然,他们没有相同的执行计划

考虑以下问题:

select name,LAG(column_id) OVER (ORDER BY system_type_id) as cid
from sys.columns
where name='name'

select * from (
select name,LAG(column_id) OVER (ORDER BY system_type_id) as cid
from sys.columns
) t
where name='name'
由于查询的逻辑处理顺序,在
SELECT
子句之前处理
WHERE
子句。因此,对于第一个查询,我们首先过滤
sys.columns
表,以仅检索具有特定名称的行,然后将
LAG()
函数仅应用于此过滤集(因此,滞后值肯定来自与过滤器匹配的另一行)

对于第二个查询,我们首先(逻辑上)处理子查询。我们在整个行集合中执行
LAG()
函数(因为子查询没有任何筛选器/
WHERE
子句),然后(在外部查询中)筛选行集合。重要的是,这意味着滞后值可能来自与最终过滤器不匹配的行


当您使用视图时,它类似于我的第二个查询。使用视图时检索的
Val
值不能保证来自
PlacementID
等于
12404
的行。您的两个查询在逻辑上不相同。所以,当然,他们没有相同的执行计划

考虑以下问题:

select name,LAG(column_id) OVER (ORDER BY system_type_id) as cid
from sys.columns
where name='name'

select * from (
select name,LAG(column_id) OVER (ORDER BY system_type_id) as cid
from sys.columns
) t
where name='name'
由于查询的逻辑处理顺序,在
SELECT
子句之前处理
WHERE
子句。因此,对于第一个查询,我们首先过滤
sys.columns
表,以仅检索具有特定名称的行,然后将
LAG()
函数仅应用于此过滤集(因此,滞后值肯定来自与过滤器匹配的另一行)

对于第二个查询,我们首先(逻辑上)处理子查询。我们在整个行集合中执行
LAG()
函数(因为子查询没有任何筛选器/
WHERE
子句),然后(在外部查询中)筛选行集合。重要的是,这意味着滞后值可能来自与最终过滤器不匹配的行


当您使用视图时,它类似于我的第二个查询。使用视图时检索到的
Val
值不能保证来自
PlacementID
等于
12404

的行,正如我提到的,它们被简化了。同样的分析仍然适用-在针对表大小写的直接查询中,逻辑上进行过滤,然后
LAG
,在视图查询中,在筛选之前,您将
LAG
ing。逻辑上,它们仍然是不同的查询。是的,延迟应该能够从与同一过滤器不匹配的行中提取,因为该值属于一个仪表,可以在不重置读数的情况下从一个位置移动到另一个位置。虽然我意识到,即使滞后值可以正确地属于以前的位置,它也没有用。因此,是的,你是正确的,它们是不同的。我知道,正如我提到的,它们被简化了。同样的分析仍然适用-在直接查询表的情况下,逻辑上你先过滤然后
LAG
,在视图查询中,你在过滤之前是
LAG
ing。逻辑上,它们仍然是不同的查询。是的,延迟应该能够从与同一过滤器不匹配的行中提取,因为该值属于一个仪表,可以在不重置读数的情况下从一个位置移动到另一个位置。虽然我意识到,即使滞后值可以正确地属于以前的位置,它也没有用。因此,是的,你是正确的,他们是不一样的。