1

我有一个 SQL Server 2005 数据库。除了对这些不同的值调用函数之外,我还需要获得不同的值。当涉及到函数调用时,我不确定 distinct 是如何工作的。例如,我有这个查询:

SELECT DISTINCT a, b, c, fcn_DoSomething(a, b, c) AS z FROM users

我猜测正在为表中的所有值调用函数 (fcn_DoSomething),而不是不同的值。我对么?如果是这样,我如何编写查询以仅在 a、b、c 的不同值上调用该函数?我知道一种选择是使用临时表,但如果有人有更好的想法,那就太好了。

谢谢

4

2 回答 2

2

这让我很好奇,所以我做了一些基本的测试。我创建了一个带有一些不同值和一些重复值的小表,一个仅执行字符串连接的函数,然后查看了以下执行计划:

Go
DBCC DROPCLEANBUFFERS 
DBCC FREEPROCCACHE 


select distinct cola, colb, dbo.sillyfunc(cola, colb)
from distincttest

--Clear the cache
Go
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE 

select cola, colb, dbo.sillyfunc(cola, colb)
from (select distinct cola, colb from distincttest) as t

在这种情况下,执行计划清楚地表明,第一个为每一行运行连接函数,但第二个首先对不同的值进行排序,然后运行该函数。但是对于少数行,它们具有相同的执行时间,当一起运行时,它们显示每行使用了总查询资源的 50%。

所以,我添加了几十万个重复行。并再次尝试。这改变了查询计划,因此它正在执行哈希匹配以获得独特性,而不是以前的排序,现在第二个版本迫使它首先选择独特性,执行速度快了十倍以上。

最后,我认为这可能只是因为 SQL Server 将我的 sillyfunc 标记为非确定性(select OBJECTPROPERTYEX(object_id('dbo.sillyfunc'), 'isdeterministic')返回 0),所以我切换到patindex,它是一个内置函数,被认为是确定性的。这给了我相同的结果,第一个版本中的每一行都调用了该函数,而第二个版本中只有少数不同的行调用了该函数。

因此,进一步的测试可能会发现诱使优化器做一些更复杂的事情的情况,但看起来如果你想在调用函数之前应用 distinct ,那么你需要使用子查询、CTE 或临时表来限制函数可以访问的内容。

于 2012-09-11T21:53:13.847 回答
1

这将确保该函数仅在不同的值上被调用。

select *, fcn_DoSomething(a, b, c) 
from
 (select distinct a,b,c FROM users) v

但是,我相信函数调用会被优化,所以它可能没有什么不同。试试看。

于 2012-09-11T20:57:56.203 回答