使用 While 循环和 Between 运算符进行查询?
Posted
技术标签:
【中文标题】使用 While 循环和 Between 运算符进行查询?【英文标题】:Using a While loop and Between operator for query? 【发布时间】:2014-07-02 13:44:25 【问题描述】:我想知道是否有更好的方法来编写此查询,或者我的做法是否最有效。
我正在浏览已在其表中转换为数值的 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
【问题讨论】:
你有一个错误set @ipcount = (select count(*) from AllIP)
将选择所有你想只在AllIP where Processed = 0
上迭代的记录
所以你喜欢做比你必须做的更多的工作?每次查找特定 IP 地址时,您都会得到相同的答案 - 但不是对该 IP 地址的每个实例都使用该答案,而是将其应用于一行,然后强迫自己稍后再查找?
@LIUFA,是的,但数据最初设置为 0。我将更改代码。
【参考方案1】:
看起来整个东西都可以用一个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)。
【讨论】:
我不确定是否可以使用 between 运算符进行内部连接。甜 @DDiVita - 一般来说,如果您可以将其放在WHERE
子句中,则可以将其放在ON
子句中以获取JOIN
。以上是关于使用 While 循环和 Between 运算符进行查询?的主要内容,如果未能解决你的问题,请参考以下文章