Sql 避免在WHERE子句中重复调用函数
我知道这很糟糕,我只是不知道如何重新写。。。感谢您的帮助Sql 避免在WHERE子句中重复调用函数,sql,tsql,function,Sql,Tsql,Function,我知道这很糟糕,我只是不知道如何重新写。。。感谢您的帮助 DECLARE @i INT, @var VARCHAR(max) SET @i = 0 WHILE 1 = 1 BEGIN INSERT INTO mrs.dbo.nav_worldcheck_results ("counter", "entity no", "entity first name",
DECLARE @i INT,
@var VARCHAR(max)
SET @i = 0
WHILE 1 = 1
BEGIN
INSERT INTO mrs.dbo.nav_worldcheck_results
("counter",
"entity no",
"entity first name",
"entity last name",
"entity full name",
"worldcheck uid",
"worldcheck first name",
"worldcheck last name",
"worldcheck full name",
"percentage match")
SELECT TOP(1) [Counter] = @i,
EN.[entity no_],
EN.[name 2],
EN.[name],
EN.[name 2] + ' ' + EN.[name] AS EntityName,
SM.uid AS WorldCheckID,
SM.[first name],
SM.[last name],
SM.[first name] + ' ' + SM.[last name] AS WorldCheckName,
dbo.Fn_calculatejarowinkler(EN.[name 2] + ' ' + EN.[name],
SM.[first name] + ' ' + SM.[last name])
FROM [NAV_LIVE].dbo.[entitytable$entity] AS EN
CROSS JOIN [NAV_LIVE].dbo.[worldcheck master] AS SM
WHERE ( EN.inactive = 0 )
AND dbo.Fn_calculatejarowinkler(EN.[name 2] + ' ' + EN.[name],
SM.[first name] + ' ' + SM.[last name]) >= .75
AND NOT EXISTS(SELECT *
FROM mrs.dbo.nav_worldcheck_results AS WCR
WHERE EN.[entity no_] = WCR.[entity no]
AND WCR.[worldcheck uid] = SM.uid)
SET @i = @i + 1
END
我想避免where语句中重复的函数调用,我尝试将所有函数都赋值为变量,然后进行处理,但我落入了一个陷阱:你不能将集合与数据检索混合在一起,我可怜的小脑袋处于星期五模式o/看起来您无法优化函数调用。如果查询需要定期运行,并且数据不改变,那么您可以考虑预先计算这个值。 我建议您多阅读一些关于连接的内容,并确定在您的情况下是否真的需要交叉笛卡尔连接(大多数情况下,您实际上需要内部连接) 您还应该咨询DBA,以确保您正在对索引列进行操作,或者看看他们是否可以添加索引来加快速度 我还将研究了解您的数据库(我假设是MSSQL)查询调优功能。值得注意的是,“解释计划”可以更深入地告诉您查询实际在做什么,以及您可以在哪里进行优化
虽然不可能事先知道查询是如何优化的,但通常不存在并且存在过滤器可能效率极低。尤其是当not exists查询上的筛选器返回多行或对非索引列进行操作时。无论哪种方式,我都建议使用
select 1
而不是select*
,因为减少所选列的数量是一种简单的优化。在这种情况下,SqlServer查询处理器(看起来像是在使用SqlServer?)不一定会对每个返回的行调用dbo.Fn\u calculatejarowinkler
函数两次(第一次在select part中,第二次在where子句中)正如您所想。如果函数是确定性的,则很可能它不这样做
您可以重写您的声明:
SELECT
...
dbo.Fn_calculatejarowinkler(EN.[name 2] + ' ' + EN.[name],
SM.[first name] + ' ' + SM.[last name])
...
FROM ... AS EN
CROSS JOIN ... AS SM
WHERE
...
AND dbo.Fn_calculatejarowinkler(EN.[name 2] + ' ' + EN.[name],
SM.[first name] + ' ' + SM.[last name]) >= .75
...
以以下方式:
SELECT
...
F.Value,
...
FROM ... AS EN
CROSS JOIN ... AS SM
CROSS APPLY (
select dbo.Fn_calculatejarowinkler(EN.[name 2] + ' ' + EN.[name],
SM.[first name] + ' ' + SM.[last name])
) F(Value)
WHERE
...
AND F.Value >= .75
...
但是,您不太可能在性能方面有所提高。感谢大家的关注并花时间回复 实际上,我已经按照Deadron的建议做了,使用了一种混合的内部连接,使用soundex作为关系,而不是交叉连接 我还在where子句中添加了“difference”的用法,而不是我的Jaro函数,性能得到了显著提高,而且它返回的命中率足以让人担心
再次感谢!您确定跨笛卡尔连接真的是这个查询应该做的吗?它几乎从来都不是……我不知道,我已经到了抓救命稻草的阶段……它应该做的是在我们的实体(人)之间找到模糊匹配表和worldchecks犯罪数据库。正如你所想象的,worldcheck数据是一个怪物…它工作起来…但速度非常慢。谢谢Deadron。这是一个可怕的查询,因为两个表之间的唯一链接是模糊匹配,你会想返回任何足够接近的数据。我可能可以使用CLR函数在SQL 2012中,这将给我带来轻微的性能优势和您的权利,如果我再仔细考虑一下,我可能会失去Exists。再次感谢您的帮助!很抱歉,我无法提供更多帮助。如果没有表架构和生成的解释计划,要优化SQL非常困难。同时还要准确描述您实际想要做的事情。