如何在事先不知道它们的数量的情况下制作多个 BETWEEN 语句?(按 IP 范围检测国家/地区)



我有Ip2LocationLite数据库,有ip_from,ip_to country_code列。

所有 IP 均为十进制格式(使用函数转换)。

所以我必须检测那些拥有来自某个国家/地区的 IP 地址的用户。例如,俄罗斯有超过 3 千个 IP 范围,我想搜索所有这些范围。

脚本如下所示:

SELECT * FROM [dbo].[USERINFO] as UserInfo
WHERE (SELECT gaminator.dbo.IPAddressToInteger (UserInfo.LastIp)) BETWEEN
    (
        SELECT [ip2location].[dbo].[ip2location_db1].ip_from FROM [ip2location].[dbo].[ip2location_db1]
        WHERE [ip2location].[dbo].[ip2location_db1].country_code = 'RU'
    )
    AND
    (
        SELECT [ip2location].[dbo].[ip2location_db1].ip_to FROM [ip2location].[dbo].[ip2location_db1]
        WHERE [ip2location].[dbo].[ip2location_db1].country_code = 'RU'
    )

最后一件事给出错误:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

这是因为 BETWEEN 期望一个音调而不是 3 千个音调。

如何对此进行编程,使其产生 3 千个 BETWEEN?(根据要检查的音调数量)

如果没有一些示例记录和预期的输出,回答这些问题可能有点棘手。 但是,如果我正确理解了您的架构,则可以使用联接而不是子查询。

SELECT 
    * 
FROM 
    [dbo].[USERINFO] as UserInfo
        INNER JOIN [ip2location].[dbo].[ip2location_db1] AS ipRange     ON UserInfo.LastIp BETWEEN ipRange.ip_to AND ipRange.ip_from
WHERE   
    ipRange.country_code = 'RU'
;

你能试试这个吗?

sELECT * FROM [dbo].[USERINFO] as UserInfo
WHERE (SELECT gaminator.dbo.IPAddressToInteger (UserInfo.LastIp)) BETWEEN
    (
        SELECT min([ip2location].[dbo].[ip2location_db1].ip_from )FROM [ip2location].[dbo].[ip2location_db1]
        WHERE [ip2location].[dbo].[ip2location_db1].country_code = 'RU'
    )
    AND
    (
        SELECT max([ip2location].[dbo].[ip2location_db1].ip_to) FROM [ip2location].[dbo].[ip2location_db1]
        WHERE [ip2location].[dbo].[ip2location_db1].country_code = 'RU'
    )

从第一个子查询中获取min/lowest值,从第二个子查询中获取max/highest值,以避免错误,以及是否要将它们用作BETWEEN子句的参数。

如果您的 IP 地址是规范的或可以按数字排序,您可以通过按 ASC 顺序对它们进行排序并选择第一行(即 SELECT TOP 1 ),并通过按 DESC 顺序对它们进行排序来获得最高的 IP 值,并选择第一行。

最新更新