如何在SQL Server中修改此查询?

时间:2015-04-21 18:01:29

标签: sql-server

我试图使用levhenstein修改此查询。我的问题是我可以在内连接查询中添加我的条件,而不是在查询的位置。

这是我的实际查询:

SELECT     
    registrosImportados.id, TVC.NOMBRETVC, 
    VIACU.NOMBREVIACU, CUT.GLOSA, 
    registrosImportados.direccion,
    dbo.fn_LevenshteinDistance(registrosImportados.direccion, VIAIU.NOMBREVIAIU, 5)
FROM         
    ACOPIOCI 
INNER JOIN
    TVC ON ACOPIOCI.IDTVC = TVC.IDTVC 
INNER JOIN
    VIACU ON ACOPIOCI.IDVIACU = VIACU.IDVIACU 
INNER JOIN
    VIAIU ON ACOPIOCI.IDVIAIU = VIAIU.IDVIAIU 
INNER JOIN
    CUT ON ACOPIOCI.IDCUT = CUT.IDCUT 
INNER JOIN
    registrosImportados ON CUT.CUT = registrosImportados.cut
WHERE
    dbo.fn_LevenshteinDistance(registrosImportados.direccion, VIAIU.NOMBREVIAIU, 5) = (SELECT MIN(M.DISTANCIA)
                     FROM 
                         (SELECT dbo.fn_LevenshteinDistance(registrosImportados.direccion, VIAIU.NOMBREVIAIU, 5) AS DISTANCIA
                          FROM ACOPIOCI 
                          INNER JOIN VIAIU ON ACOPIOCI.IDVIAIU = VIAIU.IDVIAIU 
                          WHERE ACOPIOCI.IDCUT = CUT.IDCUT) AS M
    )
    AND ACOPIOCI.IDCUT = CUT.IDCUT

这就是我想要做的事情:

SELECT      
    VIACU.NOMBREVIACU, registrosImportados.DIRECCION,
    dbo.fn_LevenshteinDistance(registrosImportados.direccion,  VIAIU.NOMBREVIAIU, 2) DIST
FROM         
    ACOPIOCI 
INNER JOIN
    TVC ON ACOPIOCI.IDTVC = TVC.IDTVC 
INNER JOIN
    VIACU ON ACOPIOCI.IDVIACU = VIACU.IDVIACU 
INNER JOIN
    VIAIU ON ACOPIOCI.IDVIAIU = VIAIU.IDVIAIU 
INNER JOIN
    CUT ON ACOPIOCI.IDCUT = CUT.IDCUT 
INNER JOIN
    registrosImportados ON CUT.CUT = registrosImportados.cut 
INNER JOIN
    (SELECT  
        MIN(dbo.fn_LevenshteinDistance(registrosImportados.direccion, VIAIU.NOMBREVIAIU, 2)
    ) AS MINDIST) M ON registrosImportados.DIST = M.MINDIST

但它不起作用。我的想法是在我的查询中获得性能。

1 个答案:

答案 0 :(得分:2)

此问题的最佳解决方案是将Levenshtein距离计算结果存储在表中,可能作为计算列,以便更新是自动的,这样您就可以在该值上放置索引。在你这样做之前,你会遇到性能问题。

也就是说,我们至少可以对查询进行一些改进。距离计算当前在查询中使用了3次:对于选择列表,在where子句中,以及计算最小距离。我希望Sql Server足够聪明,可以对SELECT和WHERE使用相同的计算(你应该通过检查执行计划来验证这一点),但我怀疑它是否能够计算最小距离。

这意味着查询有效地执行了两次:一次用于基础数据,一次用于计算最小距离;几乎所有来自基础数据查询的工作都必须重复。我们可以通过从查询的主要部分(包括levenshtein距离计算)中将未过滤的结果拉入临时表或CTE(the best option depends mainly on the size of the data),然后选择,从而加快查询速度。从该表/ CTE。这将有助于Sql Server知道如何避免为每个可能的结果记录计算两次距离。

对于此示例,我将使用CTE选项:

With Data As 
(
   SELECT     
      r.id, b.NOMBRETVC, c.NOMBREVIACU,
      CUT.GLOSA, r.direccion,
      dbo.fn_LevenshteinDistance(r.direccion,i.NOMBREVIAIU,2) As Distance
   FROM ACOPIOCI a
   INNER JOIN TVC b ON a.IDTVC = b.IDTVC 
   INNER JOIN VIACU c ON a.IDVIACU = c.IDVIACU 
   INNER JOIN VIAIU i ON a.IDVIAIU = i.IDVIAIU 
   INNER JOIN CUT ON a.IDCUT = CUT.IDCUT 
   INNER JOIN registrosImportados r ON CUT.CUT = r.cut
)
SELECT id, NOMBRETVC, NOMBREVIACU
FROM Data
WHERE Distance = (SELECT MIN(Distance) FROM DATA)

如果CTE中有很多行(超过你的可用内存量),你可以使用临时表或表变量做得更好。