2014-07-02 35 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'子句中。 –