2014-07-02 58 views
-1

我想知道是否有更好的方法來寫這個查詢,或者如果我這樣做是最有效的。使用While循環和Between運算符進行查詢?

我正在瀏覽已經在表格中轉換爲其數值的IP地址列表。然後,我需要查找地理位置數據(從MaxMind GeoIp2),其中所選IP地址位於地理位置數據的起始IP和結束IP之間。獲得地理位置數據後,我使用地理位置表的Id更新AllIP表。這將允許我稍後內部加入表格。

你會注意到我在while循環中選擇了IP地址的Id,所以我可以通過Id更新記錄。這是因爲我們可能有多個具有相同值的IP地址。由於我正在循環查看所有不想通過數字IP地址值進行更新的記錄。

declare @ipcount int 
declare @currentCount int 
declare @ipAddress bigint 
declare @id int 
declare @geoCode int 
set @currentCount = 0 
set @ipcount = (select count(*) from AllIP where Processed = 0) 

while @currentCount <[email protected] 
    BEGIN 
    set @id = (select top 1 Id from AllIP where Processed = 0) 
    set @ipAddress = (select IpAddressNumeric from AllIP where Id = @id) 
    set @geoCode = (
        SELECT dbo.[GeoLite2-City-Locations].geoname_id 
         FROM 
        dbo.[GeoLite2-City-Blocks2] 
        INNER JOIN dbo.[GeoLite2-City-Locations] ON dbo.[GeoLite2-City-Blocks2].geoname_id = dbo.[GeoLite2-City-Locations].geoname_id 
        Where @ipAddress between dbo.[GeoLite2-City-Blocks2].startIp and dbo.[GeoLite2-City-Blocks2].endIp) 

    update AllIP set Processed = 1,geocodeId = @geoCode where Id = @id 
    set @currentCount = @currentCount+1 
    end 
+0

你有一個錯誤,設置@ipcount =(從AllIP中選擇count(*))''將選擇所有你想迭代的記錄只通過'AllIP其中Processed = 0' –

+0

所以你喜歡做更多的工作, ?每當你查找一個特定的IP地址時,你都會得到相同的答案 - 而不是爲每個IP地址的實例使用這個答案,你只需要將它應用到一行,然後強迫自己以後再做一次查找? –

+0

@LIUFA,true,但數據初始設置爲0.我將更改代碼。 – DDiVita

回答

4

它看起來像整個事情可以由單個UPDATE代替:

UPDATE a 
SET Processed = 1, geoCodeId = gcb.geoname_id 
FROM 
    AllIp a 
     inner join 
    dbo.[GeoLite2-City-Blocks2] gcb 
     on 
      a.IpAddressNumeric between gcb.startIp and gcb.endIp 
WHERE 
    a.Processed = 0 

(我已經排除此刻的加盟GeoLite2-City-Locations自從加入你使用的列是同樣做爲所被選中的列)

在一般情況下,你應該喜歡寫基於集合的代碼與所有行交易在一個單獨的語句進行更新,而不是由-agonizin行工作g行(RBAR)。

+0

我不確定我是否可以使用between運算符進行內連接。 sweet – DDiVita

+0

@DDiVita - 一般來說,如果你可以把它放在'WHERE'子句中,你可以把它放在'JOIN'的'ON'子句中。 –