2012-02-29 54 views
0

我試圖找出什麼是最優化的SQL查詢來實現以下。SQL Server最佳匹配查詢與更新(T-SQL)

我有一個包含郵編/ PostalCodes一個表,讓我們假設以下結構:

table_codes:

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

等。

我的應用程序的用戶填寫了他們需要輸入他們的郵編(郵編)的輪廓。 假設有時,用戶將進入我的表沒有定義一個郵編,我想根據用戶輸入的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長於表中的任何郵政編碼,我想以獲得匹配@entered_zipcode的zip表中的最佳前綴如果@entered_zipcode比表中的任何現有代碼都短,我試圖在匹配@entered_zipcode的zip表中獲得最佳前綴

  • 在表中使用它作爲前綴,並得到最佳匹配

此外,我建立一個臨時表結構如下:

#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 
+0

你爲什麼使用臨時表? – vulkanino 2012-02-29 12:57:19

+0

我正在嘗試使用該臨時表進行一些計算。我想展示的是,我需要在一次更新操作中爲2列獲得最佳匹配zip。在我看來,我的查詢不是最理想的方式。 – mmmmmm 2012-02-29 13:07:25

回答

2

如果你改變你的臨時表是這樣的:

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

即:使用列保存用戶號碼(1或2)。這樣,您將一次更新一行。

此外,ORDER BY需要時間,你的郵政編碼設置指標?難道你不能在zipcodes表中創建一個字段「length」來預先計算郵編長度嗎?

編輯: 我在想,排序由LEN是沒有意義的,你可以刪除!如果郵政編碼不能有重複,那麼通過郵政編碼排序就足夠了。如果他們可以,LEN將永遠是平等的!如果你比較最小長度的字符串什麼 -

+0

謝謝vulkanino。我有一個ZipColumn的索引,但長度字段聽起來像一個偉大的ideea。我將嘗試這一點,並得到結果。非常感謝你。 – mmmmmm 2012-02-29 13:12:29

+0

預先計算的「zip len」在減少執行時間方面有所幫助,但卻沒有那麼多。我正在考慮你提出的另一種方法。 – mmmmmm 2012-02-29 13:20:31

+0

Oau。 Vulkanino,你真的很好。我沒有想過這件事,但你是絕對正確的。 Len的訂單沒有意義。我剛刪除了這個子句,現在執行時間縮短了3-4倍。從700ms到〜200。你搖滾! – mmmmmm 2012-02-29 13:24:27

1

你比較兩個字符串的前幾個字符?

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_ @ entered_zipcode LIKE table_codes.ZipCode + '%' *。另外,在我看來,結果的排序是錯誤的 - 較短的郵編先行。

+0

謝謝尼古拉的回答。我也嘗試過,但執行時間比我當前的查詢翻了一番。 (這是我的原始查詢沒有由Vulkanino建議的ORDER by len子句) – mmmmmm 2012-02-29 14:24:16