我想知道是否有更好的方法来编写此查询,或者我是如何做到的最有效。
我正在浏览已经转换为其表中数字值的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 <=@ipcount
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 :(得分: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
之后,因为您使用的联接列与正在选择的列相同)
通常,您应该更喜欢编写基于集合的代码来处理要在单个语句中更新的所有行,而不是逐行处理(RBAR)。< / p>