SQL Server带更新的最佳匹配查询(T-SQL)

SQL Server带更新的最佳匹配查询(T-SQL),sql,sql-server,tsql,Sql,Sql Server,Tsql,我试图找出实现以下目标的最佳SQL查询 我有一个包含ZipCodes/PostalCodes的表,让我们假设以下结构: #tmpTable ------------------------------------------------------------------------------------ ID | user1_enteredzip | user1_bestmatchzip | user2_enteredzip | user2_bestmatchzip | ----------

我试图找出实现以下目标的最佳SQL查询

我有一个包含ZipCodes/PostalCodes的表,让我们假设以下结构:

#tmpTable
------------------------------------------------------------------------------------
ID | user1_enteredzip | user1_bestmatchzip | user2_enteredzip | user2_bestmatchzip |
------------------------------------------------------------------------------------
1  |   12             |     *1234*         |       4567       |       **456**      |
2  |
3  |
4  |
表2:U代码:

ID   |  ZipCode
---------------
1       1234
2       1235
3       456
等等

我的应用程序的用户填写一个配置文件,要求他们输入ZipCode(PostalCode)。 假设有时,用户会输入我的表中未定义的ZipCode,我将尝试根据用户输入的zip建议最佳匹配

我正在使用以下查询:

Declare @entered_zipcode varchar(10)
set @entered_zipcode = '23456'


SELECT TOP 1 table_codes.ZipCode
FROM    table_codes
where   @entered_zipcode  LIKE table_codes.ZipCode + '%'
or table_codes.ZipCode + '%' like @entered_zipcode  + '%'
ORDER BY table_codes.ZipCode, LEN(table_codes.ZipCode) DESC
基本上,我正在尝试以下方法:

  • 如果@entered_zipcode比表中的任何邮政编码都长,我将尝试在zip表中获得与@entered_zipcode匹配的最佳前缀

  • 如果@entered_zipcode比表中的任何现有代码都短,我将尝试将其用作前缀,并在表中获得最佳匹配

此外,我正在构建一个具有以下结构的临时表:

#tmpTable
------------------------------------------------------------------------------------
ID | user1_enteredzip | user1_bestmatchzip | user2_enteredzip | user2_bestmatchzip |
------------------------------------------------------------------------------------
1  |   12             |     *1234*         |       4567       |       **456**      |
2  |
3  |
4  |
输入的邮政编码是用户输入的邮政编码,介于*.*之间是我的查找表中的最佳匹配代码,我正在使用下面的查询尝试获取该代码

查询似乎需要一点时间,这就是我请求帮助优化它的原因:

        update  #tmpTable
        set     user1_bestmatchzip = ( SELECT TOP 1
                                            zipcode
                                    FROM    table_codes
                                    where   #tmpTable.user1_enteredzip  LIKE table_codes.zipcode + '%'
                                            or table_codes.zipcode + '%' like #tmpTable.user1_enteredzip + '%'
                                    ORDER BY table_codes.zipcode, LEN(table_codes.zipcode) DESC
                                  ),
                user2_bestmatchzip = ( SELECT TOP 1
                                            zipcode
                                    FROM    table_codes
                                    where   #tmpTable.user2_enteredzip  LIKE table_codes.zipcode + '%'
                                            or table_codes.zipcode + '%' like #tmpTable.user2_enteredzip + '%'
                                    ORDER BY table_codes.zipcode, LEN(table_codes.zipcode) DESC
                                  )
         from #tmpTable

如果将临时表更改为:

id  |  user | enteredzip | bestmatchzip 
10  |  1    | 12345      | 12345
20  |  2    | 12         | 12345
即:使用列保存用户编号(1或2)。这样,您将一次更新一行

另外,
orderby
需要时间,您是否在zipcode上设置了索引?您不能在zipcodes表中创建一个字段“length”来预计算zipcodes lenghts吗

编辑:
我在想由LEN订购是没有意义的,你可以删除它!如果zipcode不能有重复项,那么按zipcode排序就足够了。如果他们可以,那么
LEN
将始终相等

如果将临时表更改为:

id  |  user | enteredzip | bestmatchzip 
10  |  1    | 12345      | 12345
20  |  2    | 12         | 12345
即:使用列保存用户编号(1或2)。这样,您将一次更新一行

另外,
orderby
需要时间,您是否在zipcode上设置了索引?您不能在zipcodes表中创建一个字段“length”来预计算zipcodes lenghts吗

编辑:
我在想由LEN订购是没有意义的,你可以删除它!如果zipcode不能有重复项,那么按zipcode排序就足够了。如果他们可以,那么
LEN
将始终相等

您正在比较两个字符串的第一个字符-如果您比较最小长度的子字符串呢

select top 1 zipcode
from table_zipcodes
where substring(zipcode, 1, case when len(zipcode) > len (@entered_zipcode) then len(@entered_zipcode) else len (zipcode) end) 
    = substring (@entered_zipcode, 1, case when len(zipcode) > len (@entered_zipcode) then len(@entered_zipcode) else len (zipcode) end) 
order by len (zipcode) desc

这将删除或,并允许在@entered_zipcode(如表_codes.zipcode+'%')*)中使用索引*。另外,在我看来,结果的顺序是错误的——先是较短的Zipcode。

您正在比较两个字符串的第一个字符——如果您比较最小长度的子字符串呢

select top 1 zipcode
from table_zipcodes
where substring(zipcode, 1, case when len(zipcode) > len (@entered_zipcode) then len(@entered_zipcode) else len (zipcode) end) 
    = substring (@entered_zipcode, 1, case when len(zipcode) > len (@entered_zipcode) then len(@entered_zipcode) else len (zipcode) end) 
order by len (zipcode) desc

这将删除或,并允许在@entered_zipcode(如表_codes.zipcode+'%')*)中使用索引*。另外,在我看来,结果的顺序是错误的——先是较短的Zipcode。

为什么要使用临时表?我正在尝试使用临时表进行一些计算。我想展示的是,我需要在一次更新操作中获得两列的最佳匹配zip。在我看来,我的查询不是最理想的方式。为什么要使用临时表?我正在尝试使用临时表进行一些计算。我想展示的是,我需要在一次更新操作中获得两列的最佳匹配zip。在我看来,我的查询并不是最理想的方式。谢谢你。我有一个关于ZipColumn的索引,但是长度字段听起来像是一个很棒的主意。我要试试这个,然后带着结果回来。非常感谢。预先计算的“zip-len”有助于减少执行时间,但没有那么多。我正在考虑你建议的另一种办法。瓦卡尼诺,你真的很好。我没有想到这一点,但你是绝对正确的。由Len订购毫无意义。我刚刚删除了这个条款,现在执行时间缩短了3-4倍。从700毫秒到200毫秒。你太棒了!谢谢你,瓦卡尼诺。我有一个关于ZipColumn的索引,但是长度字段听起来像是一个很棒的主意。我要试试这个,然后带着结果回来。非常感谢。预先计算的“zip-len”有助于减少执行时间,但没有那么多。我正在考虑你建议的另一种办法。瓦卡尼诺,你真的很好。我没有想到这一点,但你是绝对正确的。由Len订购毫无意义。我刚刚删除了这个条款,现在执行时间缩短了3-4倍。从700毫秒到200毫秒。你太棒了!谢谢尼古拉的回答。我也尝试了你的aproach,但是执行时间比我当前的查询要长一倍。(这是我最初的问题,没有Vulkanino建议的ORDER by len条款)谢谢Nikola的回答。我也尝试了你的aproach,但是执行时间比我当前的查询要长一倍。(这是我的原始查询,没有Vulkanino建议的ORDER by len条款)