0

我知道这很糟糕,我只是不知道如何重写它......任何帮助表示赞赏!

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/

4

3 回答 3

0

看起来您无法优化函数调用。如果查询需要定期运行并且数据不会更改,您可能会考虑预先计算此值。

我建议您阅读有关连接的更多信息,并确定在您的情况下是否真的需要交叉笛卡尔(大多数情况下您实际上想要内部连接)。http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

您还真的应该咨询您的 DBA,以确保您正在对索引列进行操作,或者查看他们是否可以添加索引以加快速度。

我还将研究了解您的数据库(我假设是 MSSQL)查询调优功能。值得注意的是,解释计划可以更深入地告诉您查询实际在做什么以及可以优化的地方。

虽然不可能事先知道查询是如何优化的,但通常 NOT EXISTS 和 EXISTS 过滤器的效率可能非常低。特别是如果不存在查询上的过滤器返回多于一行,或者如果它对非索引列进行操作。无论哪种方式,我都推荐select 1而不是select *因为减少选择的列数是一种简单的优化。

于 2013-10-25T15:08:07.593 回答
0

在这种情况下,SqlServer 查询处理器(看起来像您使用 SqlServer?)并不一定dbo.Fn_calculatejarowinkler像您想象的那样为每个返回的行调用两次函数(第一次在 select 部分,第二次在 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
    ...

但不太可能会提高性能。

于 2013-10-25T21:31:59.830 回答
0

感谢大家寻找并花时间回复。

我实际上已经按照 Deadron 的建议进行了操作,并使用了内部连接的混合,使用 soundex 作为关系而不是交叉连接。

我还在 where 子句中添加了“差异”的使用,而不是我的 Jaro 函数,并且性能得到了显着提高,并且它返回的命中率足以让我担心。

再次感谢!

于 2013-10-28T09:28:32.003 回答