我有一个用户定义的函数(例如myUDF(a,b)
),它返回一个整数。
我正在尝试确保此函数只被调用一次,其结果可以用作WHERE
子句中的条件:
SELECT col1, col2, col3,
myUDF(col1,col2) AS X
From myTable
WHERE x>0
SQL Server尝试将x
检测为列,但它实际上是计算值的别名。
如何重新编写此查询,以便可以对计算值进行过滤,而不必多次执行UDF?
答案 0 :(得分:7)
With Tbl AS
(SELECT col1, col2, col3, myUDF(col1,col2) AS X
From table myTable )
SELECT * FROM Tbl WHERE X > 0
答案 1 :(得分:5)
如果您使用的是SQL Server 2005及更高版本,则可以使用“交叉应用”:
Select T.col1, T.col2, FuncResult.X
From Table As T
Cross Apply ( Select myUdf(T.col1, T.col2) As X ) As FuncResult
Where FuncResult.X > 0
答案 2 :(得分:4)
试
SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X
From myTable
WHERE dbo.myUDF(col1,col2) >0
但请注意,这会导致扫描,因为它不是SARGable
这是另一种方式
select * from(
SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X
From myTable ) as y
WHERE x>0
答案 3 :(得分:2)
SQL Server不允许您通过别名引用列。您必须两次写出该列:
SELECT col1, col2, col3, myUDF(col1,col2) AS X
From table myTable
WHERE myUDF(col1,col2) > 0
或者使用子查询:
SELECT *
FROM (
SELECT col1, col2, col3, myUDF(col1,col2) AS X
From table myTable
) as subq
WHERE x > 0
答案 4 :(得分:1)
根据udf及其有用或经常使用的情况,您可以考虑将其作为computed column添加到表中。然后,您可以正常过滤列,而不必在查询中写出该函数。
答案 5 :(得分:0)
我不是100%肯定你在做什么,但由于x不是一个列,我会从你的SQL语句中删除它,所以你有:
SELECT col1, col2, col3, myUDF(col1,col2) AS X From myTable
然后将条件添加到您的代码中,这样您只能在x > 0
答案 6 :(得分:0)
你的问题最好通过“With”条款回答(CTE我认为,在MSSS中)。
真正最好的问题是:我是否应该存储此计算值,或者每次查询表时重新计算每一行。
表格中有10行,总共有10行吗?
是否经常添加行?
您是否有适当的清除策略或只是让它成长?
每月只查询一次该表吗?
如果这是一个“长时间运行”的功能(即使你已经优化了地狱之后),你为什么要多次执行它?
你问了一次,但每个查询你确实要求每行一次。
将答案存储在索引或“虚拟列”中
优点:
每行计算一次。 查询时间不会线性增长。
缺点: 增加插入/更新时间
每次计算
优点:
插入/更新时间优化
缺点: 查询时间随行计数增加。 (不可扩展)
如果您每个月要查询一次,为什么要关心性能有多糟糕,请调整一些对您的操作产生重大影响的事情(非常轻微的滑稽)。
如果你没有插入一堆(取决于你的硬件)每秒的行数,那么预先花费这么多时间会产生很大的不同吗?