减少SQL存储过程中的比较次数

时间:2012-04-05 07:33:29

标签: sql sql-server

我创建了一个存储过程。

以下是要求:

  • 首先匹配公司名称和人名。
  • 如果未找到匹配项,则应对地址,城市和人名进行第二场比赛。
  • 如果未找到匹配项,则应对zip和人名进行第三场比赛。

我写的是

exec('insert into ProcessedFile_'+@fileuplodedId +' ('+@ConcatAppendedField+ ',UploadedB2bFiled_id) select '+@concatAppendFieldForSelect +',B2bFiled_id from UploadedFile_'+@fileuplodedId+' a , b2bdb b where ((a.CompanyDomain = b.domain and ISNULL(a.CompanyDomain,'''') <> '''' and a.CompanyDomain is not null and a.Name=b.Name)) group by B2bFiled_id,' + @concatAppendFieldForGroupBy ) 

exec('insert into ProcessedFile_'+@fileuplodedId +' ('+@ConcatAppendedField+ ',UploadedB2bFiled_id) select '+@concatAppendFieldForSelect +',B2bFiled_id from UploadedFile_'+@fileuplodedId+' a , b2bdb b where (((a.CompanyDomain is null or a.CompanyDomain !=b.domain) and a.Address1 = b.address and a.City = b.city and a.Name = b.Name )) group by B2bFiled_id,' + @concatAppendFieldForGroupBy) 

exec('insert into ProcessedFile_'+@fileuplodedId +' ('+@ConcatAppendedField+ ',UploadedB2bFiled_id) select '+@concatAppendFieldForSelect +',B2bFiled_id from UploadedFile_'+@fileuplodedId+' a , b2bdb b where ((((a.CompanyDomain is null or a.CompanyDomain !=b.domain) and (a.Address1 = b.address and a.City = b.city and a.Name = b.Name )) and a.Zip = b.Zip and a.Name = b.Name )) group by B2bFiled_id,' + @concatAppendFieldForGroupBy)`

但这绝对是低效的,因为在每个陈述(第一个除外)我比较之前我做的所有字段,因为我在第一个比较公司名称和人名,在第二个陈述中我再次比较那些字段(公司)姓名和人名。)

如何摆脱这个?

1 个答案:

答案 0 :(得分:2)

如果插入了行,则可以在每次插入后添加RETURN语句以退出批处理。这样您就不必从先前的查询中删除条件。 e.g。

DECLARE @QueryStart NVARCHAR(1000), @QueryEnd NVARCHAR(1000)
SET @QueryStart = ' INSERT INTO ProcessedFile_' + @FileUploadID + 
                ' (' + @ConcatAppendField + ', UploadedB2bFiled_ID) ' + 
                ' SELECT ' + @ConcatAppendFieldForSelect + ', B2bFiled_ID ' + 
                ' FROM UploadFile_' + @FileUploadedID + ' a, B2bDB b '

SET @QueryEnd = ' GROUP BY B2bFiled_ID, ' + @ConcatAppendFieldForGroupBy    

DECLARE @Query NVARCHAR(1000)
SET @Query = @QueryStart + 
            ' WHERE a.CompanyDomain = b.Domain ' + 
            ' AND   ISNULL(a.CompanyDomain, '''') != '''' ' + 
            ' AND   a.CompanyDomain IS NOT NULL ' +
            ' AND   a.Name = b.Name ' +
            @QueryEnd

EXECUTE SP_EXECUTESQL @Query

IF (@@ROWCOUNT > 0)
    RETURN

SET @Query = @QueryStart + 
            ' WHERE a.Address1 = b.Address ' + 
            ' AND   a.City = b.City ' + 
            ' AND   a.Name = b.Name ' + 
            @QueryEnd

EXECUTE SP_EXECUTESQL @Query

IF (@@ROWCOUNT > 0)
    RETURN

SET @Query = @QueryStart + 
            ' WHERE a.Zip = b.Zip ' + 
            ' AND   a.Name = b.Name ' + 
            @QueryEnd

EXECUTE SP_EXECUTESQL @Query

我复制了你的子句,但值得指出的是,可以简化以下where子句。

WHERE a.CompanyDomain = b.Domain
AND   ISNULL(a.CompanyDomain, '') != '' 
AND   a.CompanyDomain IS NOT NULL

由于NULL不等于任何东西,甚至不是NULL,如果a.CompanyDomain为NULL,那么它永远不能等于b.Domain,所以这可以简化为

WHERE NULLIF(a.CompanyDomain, '') = b.Domain

<强> ADENDUM

好的,正如我现在所理解的那样,如果第一个查询返回结果,你不想中止执行,你只想排除第一个查询从第二个查询插入的任何内容,以及第一个和第二个查询插入的任何内容。 3,所以你可以避免重复插入?如果是这种情况,我认为你可以通过将所有标准组合成一个查询来解决这个问题:

DECLARE @Query NVARCHAR(1000)
SET @Query = ' INSERT INTO ProcessedFile_' + @FileUploadID + 
            ' (' + @ConcatAppendField + ', UploadedB2bFiled_ID)
            SELECT ' + @ConcatAppendFieldForSelect + ', B2bFiled_ID
            FROM    UploadFile_' + @FileUploadedID + ' a 
                    INNER JOIN B2bDB b 
                        ON a.Name = b.Name
            WHERE   NULLIF(a.CompanyDomain, '''') = b.Domain
            OR      (a.Address1 = b.Address AND a.City = b.City) 
            OR      a.Zip = b.Zip
            GROUP BY B2bFiled_ID, ' + @ConcatAppendFieldForGroupBy  

EXECUTE SP_EXECUTESQL @QUERY

如果这不是我需要的,我认为您可能必须使用3个插入的原始解决方案,因为它听起来像您正在使用第二个中第一个查询插入的数据,而第一个和第二个插入的数据第三个。