SQL Server查询中的操作顺序

SQL Server查询中的操作顺序,sql,sql-server,subquery,Sql,Sql Server,Subquery,我有下面的查询选择项目和它的功能之一,从十万行的项目 但我担心子查询的性能。是在where条款之后还是之前执行 假设我从10000个项目中选择了25个项目,那么这个子查询将只对25个项目或10000个项目执行 declare @BlockStart int = 1 , @BlockSize int = 25 ; select *, ( select Value_Float from Features B where B.Feature_ModelID = Itm.

我有下面的查询选择项目和它的功能之一,从十万行的项目

但我担心子查询的性能。是在where条款之后还是之前执行

假设我从10000个项目中选择了25个项目,那么这个子查询将只对25个项目或10000个项目执行

declare @BlockStart int = 1
    , @BlockSize int = 25
;
select *, (
    select Value_Float
    from Features B
    where B.Feature_ModelID = Itm.ModelID
        and B.Feature_PropertyID = 5
    ) as Price  
from (
    select *
        , row_number() over (order by ModelID desc) as RowNumber
    from Models
) Itm 
where Itm.RowNumber >= @BlockStart
    and Itm.RowNumber < @BlockStart + @BlockSize
order by ModelID desc
FROM子句中的子查询生成一整套结果,但SELECT子句中的子查询通常会!只能对最终结果集包含的记录运行

与SQL中的所有内容一样,其中也涉及到一个查询优化器,它有时可能会决定创建看似奇怪的执行计划。在这种情况下,我相信我们可以非常自信,但我需要注意对SQL语言的操作顺序进行全面概括

接下来,您是否看到了Sql Server 2012及更高版本中可用的OFFSET/FECTH语法?这似乎是处理@BlockStart和@BlockSize值的更好方法,特别是当您在另一个列上分页时,链接显示了一个更快的方法

此外,如果您知道每个ModelID中只有一条Feature_PropertyID=5的Features记录,那么您将有可能再次进行归纳,使用联接获得更好的性能:

SELECT m.*, f.Value_Float As Price
FROM Models m
LEFT JOIN Features f ON f.Feature_ModelID = m.ModelID AND f.Feature_PropertyID = 5
ORDER BY m.ModelID DESC
OFFSET @BlockStart ROWS FETCH NEXT @BlockSize ROWS ONLY
如果您不能做出保证,您可以通过应用操作获得更好的性能:

SELECT m.*, f.Value_Float As Price
FROM Models m
OUTER APPLY (
    SELECT TOP 1 Value_Float 
    FROM Features f 
    WHERE f.Feature_ModelID = m.ModelID AND f.Feature_PropertyID = 5
) f
ORDER BY m.ModelID DESC
OFFSET @BlockStart ROWS FETCH NEXT @BlockSize ROWS ONLY
最后,这闻起来像是实体属性值模式的另一个变体。。。虽然它有自己的位置,但通常应该是最后的选择。

FROM子句中的子查询会生成一整套结果,但SELECT子句中的子查询通常会!只能对最终结果集包含的记录运行

与SQL中的所有内容一样,其中也涉及到一个查询优化器,它有时可能会决定创建看似奇怪的执行计划。在这种情况下,我相信我们可以非常自信,但我需要注意对SQL语言的操作顺序进行全面概括

接下来,您是否看到了Sql Server 2012及更高版本中可用的OFFSET/FECTH语法?这似乎是处理@BlockStart和@BlockSize值的更好方法,特别是当您在另一个列上分页时,链接显示了一个更快的方法

此外,如果您知道每个ModelID中只有一条Feature_PropertyID=5的Features记录,那么您将有可能再次进行归纳,使用联接获得更好的性能:

SELECT m.*, f.Value_Float As Price
FROM Models m
LEFT JOIN Features f ON f.Feature_ModelID = m.ModelID AND f.Feature_PropertyID = 5
ORDER BY m.ModelID DESC
OFFSET @BlockStart ROWS FETCH NEXT @BlockSize ROWS ONLY
如果您不能做出保证,您可以通过应用操作获得更好的性能:

SELECT m.*, f.Value_Float As Price
FROM Models m
OUTER APPLY (
    SELECT TOP 1 Value_Float 
    FROM Features f 
    WHERE f.Feature_ModelID = m.ModelID AND f.Feature_PropertyID = 5
) f
ORDER BY m.ModelID DESC
OFFSET @BlockStart ROWS FETCH NEXT @BlockSize ROWS ONLY

最后,这闻起来像是实体属性值模式的另一个变体。。。虽然它有自己的位置,但通常应该是最后的选择。

看看执行计划。这是一个很好的起点。通常,where在select之前过滤,所以它可能是25次。选择where部分之后执行的查询的一部分,这就是为什么select部分的子查询只对25条记录有效。但这并不意味着它执行了25次。可能会对25条记录执行一次。为什么不使用OFFSET@BlockStart ROWS FETCH NEXT@BlockSize ROWS,而不是使用where子句来确定相同的内容?我确实认为您需要在查询中输入数字,而不是作为参数,我认为如果您尝试这样做会出错,因为变量可以作为执行的一部分进行更改查看执行计划。这是一个很好的起点。通常,where在select之前过滤,所以它可能是25次。选择where部分之后执行的查询的一部分,这就是为什么select部分的子查询只对25条记录有效。但这并不意味着它执行了25次。可能会对25条记录执行一次。为什么不使用OFFSET@BlockStart ROWS FETCH NEXT@BlockSize ROWS,而不是使用where子句来确定相同的内容?我确实认为您需要将数字放入查询中,而不是作为参数,我认为如果您尝试这样做是错误的,因为变量可以作为查询的一部分进行更改execution@Andrew是的,你可以。去试试吧。我想你现在可以了,尽管你的开始应该是-1,因为原来的>=query@Andrew是的,你可以。去试试吧。我想你现在可以了,尽管你的开始应该是-1,因为原始查询中的>=