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非常困难。同时还要准确描述您实际想要做的事情。