I am trying to find out what’s the most optimized SQL Query to achieve the following.
I have a table containing ZipCodes/PostalCodes, let’s assume the following structure:
table_codes:
ID | ZipCode
---------------
1 1234
2 1235
3 456
and so on.
The users of my application fill up a profile where they are required to enter their ZipCode (PostalCode).
Assuming that sometimes, the user will enter a ZipCode not defined in my table, I am trying to suggest a Best Match based on the zip entered by the user.
I am using the following query:
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
Basically, I am trying the following:
-
if the @entered_zipcode is longer than any zip code in the table, I am trying to get to get the best prefix in the zip table matching the @entered_zipcode
-
if the @entered_zipcode is shorter than any existing code in the table, I am trying to use it as a prefix and get the best match in the table
Moreover, I am building a temp table with the following structure:
#tmpTable
------------------------------------------------------------------------------------
ID | user1_enteredzip | user1_bestmatchzip | user2_enteredzip | user2_bestmatchzip |
------------------------------------------------------------------------------------
1 | 12 | *1234* | 4567 | **456** |
2 |
3 |
4 |
Entered zip is the one the user enters and the code between * .. * is the best matching code from my lookup table, that I am trying to get using the query below.
The query seems to take a little bit to long and this is why I am asking for help in optimizing it:
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
What if you change your temp table to be like:
That is: use a column to save the user number (1 or 2). This way you will update one row at a time.
Also, the
ORDER BYtakes time, did you set indices on the zipcode? Couldn’t you create a field “length” in the zipcodes table to pre-compute the zipcodes lenghts?EDIT:
I was thinking that ordering by LEN makes no sense, you could remove that! If the zipcodes cannot have duplicates, then ordering by the zipcode is just enought. If they can though, the
LENwill always be equal!