作为 UDF 结果的列上的 Where 子句

发布于 2024-09-08 16:33:38 字数 318 浏览 5 评论 0原文

我有一个返回整数的用户定义函数(例如myUDF(a,b))。

我试图确保此函数仅被调用一次,并且其结果可以用作 WHERE 子句中的条件:

SELECT col1, col2, col3, 
       myUDF(col1,col2) AS X
From myTable
WHERE x>0

SQL Server 尝试将 x 检测为列,但是它实际上是计算值的别名。

如何重写此查询,以便可以对计算值进行过滤,而无需多次执行 UDF?

I have a user defined function (e.g. myUDF(a,b)) that returns an integer.

I am trying to ensure this function will be called only once and its results can be used as a condition in the WHERE clause:

SELECT col1, col2, col3, 
       myUDF(col1,col2) AS X
From myTable
WHERE x>0

SQL Server tries to detect x as column, but it's really an alias for a computed value.

How can you re-write this query so that the filtering can be done on the computed value without having to execute the UDF more than once?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

装纯掩盖桑 2024-09-15 16:33:38
With Tbl AS 
(SELECT col1, col2, col3, myUDF(col1,col2) AS X  
        From table myTable  )

SELECT * FROM Tbl WHERE X > 0
With Tbl AS 
(SELECT col1, col2, col3, myUDF(col1,col2) AS X  
        From table myTable  )

SELECT * FROM Tbl WHERE X > 0
梅窗月明清似水 2024-09-15 16:33:38

如果您使用的是 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

If you are using SQL Server 2005 and beyond, you can use Cross Apply:

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
美人如玉 2024-09-15 16:33:38

尝试

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

try

SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X 
From myTable 
WHERE dbo.myUDF(col1,col2) >0

but be aware that this will cause a scan since it is not SARGable

Here is another way

select * from(
SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X 
From myTable ) as  y 
WHERE x>0
逐鹿 2024-09-15 16:33:38

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

SQL Server does not allow you to reference columns by alias. You either have to write out the column twice:

SELECT  col1, col2, col3, myUDF(col1,col2) AS X 
From    table myTable 
WHERE   myUDF(col1,col2) > 0

Or use a subquery:

SELECT  *
FROM    (
        SELECT col1, col2, col3, myUDF(col1,col2) AS X 
        From table myTable 
        ) as subq
WHERE   x > 0
所有深爱都是秘密 2024-09-15 16:33:38

根据 udf 以及它的有用性或使用频率,您可以考虑将其作为 计算列。然后,您可以像平常一样过滤列,而不必在查询中写出该函数。

Depending on the udf and how useful or frequently used it is, you may consider adding it to the table as a computed column. You could then filter on the column as normal and not have to write out the function at all in queries.

怀里藏娇 2024-09-15 16:33:38

我不是 100% 确定你在做什么,但由于 x 不是列,我会将其从你的 SQL 语句中删除,这样你就可以:

SELECT col1, col2, col3, myUDF(col1,col2) AS X From myTable

然后将条件添加到你的代码中,这样你只在 x > 时调用它; 0

I'm not 100% sure what you are doing but since x isn't a column I would remove it from your SQL statement so you have :

SELECT col1, col2, col3, myUDF(col1,col2) AS X From myTable

And then add the condition to your code so you only call it when x > 0

浅笑轻吟梦一曲 2024-09-15 16:33:38

您的问题最好由“With”条款(我认为是 MSSS 中的 CTE)来回答。

实际上最好的问题是:每次查询表时,我应该存储这个计算值还是为每一行重新计算它。

表中有 10 行并且总是 10 行吗?

行是否不断添加?

您是否制定了清理策略,或者只是任其发展?

每月只查询该表一次?

如果这是一个“长时间运行”的函数(即使你已经优化了它),为什么你想要多次执行它呢?

您请求一次,但实际上您是在每行、每个查询请求一次。

将答案存储在索引或“虚拟列”中

优点:

每行精确计算一次。
查询时间不会线性增长。

缺点:
增加插入/更新时间

每次计算

优点:

插入/更新时间优化

缺点:
查询时间随着行数的增加而增加。 (不可扩展)

如果你每月查询一次,为什么你关心性能有多糟糕,去调整一些实际上对你的操作有很大影响的东西(非常有点滑稽)。

如果您没有每秒插入一堆(取决于您的硬件)行,那么预先花费这些时间会产生很大的不同吗?

Your question is best answered by the "With" clauses (CTE's I think, in MSSS).

Really the best question is: Should I store this computed value or recalculate it for every row, each and every time I query the table.

Are there 10 rows in the table and always 10 rows?

Are rows being added constantly?

Do you have a purge strategy in place or just let it grow?

Query that table only once a month?

If this is a "long running" function (even after you've optimized the hell out of it), why do you want to execute it more than once, ever?

You asked for once, but you are really asking for once per row, per query.

Storing the answer in an index or "virtual column"

Pros:

Calculate exactly once per row.
Query times don't grow linearly.

Cons:
Increases insert/update time

Calculating every time

Pros:

Insert/update time optimized

Cons:
Query time grows with row count. (not scalable)

If you're querying once a month, why do you care how bad the performance is, go tune something that actually has a big impact on your operations (very slightly facetious).

If you're not inserting a bunch (depends on your hardware) of rows per second, is spending that time up front going to make a big difference?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文