SQL Server запрос наилучшего соответствия с обновлением (T-SQL) - PullRequest
0 голосов
/ 29 февраля 2012

Я пытаюсь выяснить, что является наиболее оптимизированным SQL-запросом для достижения следующего:

У меня есть таблица, содержащая ZipCodes / PostalCodes, давайте предположим следующую структуру:

table_codes:

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

и т. Д.

Пользователи моего приложения заполняют профиль, где им необходимо ввести свой ZipCode (PostalCode).Предполагая, что иногда пользователь вводит ZipCode, не определенный в моей таблице, я пытаюсь предложить лучшее совпадение на основе введенного пользователем почтового индекса.

Я использую следующий запрос:

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, соответствующая @ input_zipcode

  • , если @entered_zipcode короче любого существующего кода в таблице, я пытаюсь использовать его в качестве префикса и получить лучшее совпадение в таблице

Кроме того, я создаю временную таблицу со следующей структурой:

#tmpTable
------------------------------------------------------------------------------------
ID | user1_enteredzip | user1_bestmatchzip | user2_enteredzip | user2_bestmatchzip |
------------------------------------------------------------------------------------
1  |   12             |     *1234*         |       4567       |       **456**      |
2  |
3  |
4  |

Введенный zip - это тот, который вводит пользователь, и код между * .. *это лучший соответствующий код из моей таблицы поиска, который я пытаюсь использовать, используя приведенный ниже запрос.

Похоже, что запрос занимает немного много времени, и поэтому я прошу помощи в его оптимизации:

        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

Ответы [ 2 ]

2 голосов
/ 29 февраля 2012

Что если вы измените временную таблицу так:

id  |  user | enteredzip | bestmatchzip 
10  |  1    | 12345      | 12345
20  |  2    | 12         | 12345

То есть: используйте столбец для сохранения номера пользователя (1 или 2). Таким образом, вы будете обновлять по одной строке за раз.

Кроме того, ORDER BY занимает много времени, вы установили индексы для почтового индекса? Не могли бы вы создать поле "длина" в таблице почтовых индексов для предварительного вычисления длин почтовых индексов?

EDIT: Я думал, что заказ по LEN не имеет смысла, вы можете удалить это! Если почтовые индексы не могут иметь дубликаты, то порядок по почтовому индексу достаточно. Но если они могут, LEN всегда будет равным!

1 голос
/ 29 февраля 2012

Вы сравниваете первые символы обеих строк - что, если вы сравниваете подстроки минимальной длины?

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

Это удалит ИЛИ и разрешит использование индекса * in_ @tered_zipcode LIKE table_codes.ZipCode + '%' *. Кроме того, мне кажется, что порядок результатов неправильный - короче почтовые индексы идут первыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...