我对CROSS APPLY
有参数化表值函数的问题。
这是简化的伪代码示例:
SELECT *
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) AS lor
CROSS APPLY dbo.HeavyTableValuedFunction(lor.ID) AS htvf
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
WHERE ...
LOT_OF_ROWS_TABLE
上的内部选择返回许多行。LOT_OF_ROWS_TABLE
和ANOTHER_TABLE
只返回一行或几行。 我的问题:
对于从LOT_OF_ROWS_TABLE
返回的所有行,都会调用该函数,而不管在加入ANOTHER_TABLE
时数据是否会受到限制。
选择必须采用所示格式 - 它是生成的,实际上它更加困难。
当我尝试重写它时,它可以非常快,但它不能像这样重写:
SELECT *
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) AS lor
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
CROSS APPLY dbo.HeavyTableValuedFunction(at.ID) AS htvf
WHERE ...
我想知道:
是否有任何设置或提示或强制选择仅为最终受限制的行调用函数的东西?
谢谢。
修改
表值函数非常复杂:http://pastebin.com/w6azRvxR。 我们所讨论的选择是“用户配置”并生成:http://pastebin.com/bFbanY2n。
答案 0 :(得分:2)
您可以使用表变量或临时表
将此查询分为两部分SELECT lor.*,at.* into #tempresult
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) lor
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
WHERE ...
现在做表值函数的耗时部分
SELECT * FROM #tempresult
CROSS APPLY dbo.HeavyTableValuedFunction(#tempresult.ID) AS htvf
答案 1 :(得分:1)
我相信这就是你要找的东西。
Plan Forcing Scenario: Create a Plan Guide to Force a Plan Obtained from a Rewritten Query
基本上它描述了重写查询以使用正确的连接顺序获取生成的计划。然后保存该计划并强制您现有的查询(不会更改)使用您保存的计划。
我放入的BOL链接甚至给出了一个特定的例子,即重新编写查询,以不同的顺序放置连接并使用FORCE ORDER
提示。然后使用sp_create_plan_guild
从重写的查询中获取计划,并将其用于原始查询。
答案 2 :(得分:0)
是和否......如果没有样本数据IN和结果OUT,很难在你想要实现的目标之间进行比较,以比较结果。
我想知道:
是否存在强制选择呼叫的设置或提示或其他内容 函数仅适用于最终受限制的行?
所以我会直接回答你上面的问题(3年后!!),直接声明:
您需要了解CTE和CROSS APPLY之间的区别 与INNER JOIN相比,为什么在你的情况下使用CROSS APPLY 必要。您“可以”在您的函数中获取代码并应用它 使用CTE将SQL语句转换为单个SQL语句。
即:
基本上,这样的事情......
WITH t2o AS
(
SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn
FROM t2
)
SELECT t1.*, t2o.*
FROM t1
INNER JOIN
t2o
ON t2o.t1_id = t1.id
AND t2o.rn <= 3
应用您的查询来推断您想要ONCE的日期,并使用CTE,然后使用CROSS APPLY应用您的第二个SQL。
你别无选择。你不能在一个SQL中做你想做的事。