SQL 中的 IP 范围

IP range in SQL

我有几十万个IP,想确定哪些在一定范围内。 范围:

64.233.160.0 /  8192
66.102.0.0 / 4096
66.249.64.0 / 8192
72.14.192.0 / 16384
74.125.0.0  / 65536
209.85.128.0 / 32768
216.239.32.0 / 8192

所以我将这些范围转换为以下内容:

64.233.160.0    -   64.233.192.0
66.102.0.0      -   66.102.16.0
66.249.64.0     -   66.249.96.0
72.14.192.0     -   72.15.0.0
74.125.0.0      -   74.126.0.0
209.85.128.0    -   209.86.0.0
216.239.32.0    -   216.239.64.0

所以现在我想查询一个 IP 地址是否在这些范围内。 SQL 不会理解八位字节,所以我不知道该怎么做。

可以使用一些 Hex2Dec/Dec2Hex 转换吗?

我想这应该是以前做过的事情,我敢肯定我不是第一个尝试使用 ip 范围在列表中识别特定 ip 的人。

我将查找多个 IP 地址,因此一些可能是 20.0.1.123,另一个可能是 124.123.123.1,即八位字节的格式将不同

IP 号码实际上只是整数。您在这里所做的是将它们保存为人类可读的字符串。您需要将它们转换回它们的原始整数表示形式,以便您可以使用正常的 BETWEEN 进行查询。

您可以为此使用 IP functions

PARSE_IP('64.233.160.0') returns 1089052672

然后您可以将它们包装在 BETWEEN 状态。

Pentium10 的答案对于 Legacy Bigquery 语法是正确的。对于碰巧使用 StandardSQL Bigquery 语法的任何人,您正在寻找这个:

NET.IP_FROM_STRING('64.233.160.0') returns 1089052672

对于 BigQuery Standard SQL 将 IP 转换为整数的方法如下

#standardSQL  
SELECT NET.IPV4_TO_INT64(NET.IP_FROM_STRING('64.233.160.0'))   

与 SQL UDF 一起使用可以简化为如下所示

#standardSQL
CREATE TEMP FUNCTION ip2int(ip STRING) AS (
  NET.IPV4_TO_INT64(NET.IP_FROM_STRING(ip))
);
WITH Ranges AS (
  SELECT '64.233.160.0' AS IP1, '64.233.192.0' AS IP2 UNION ALL
  SELECT '66.102.0.0', '66.102.16.0' UNION ALL
  SELECT '66.249.64.0', '66.249.96.0' UNION ALL
  SELECT '72.14.192.0', '72.15.0.0' UNION ALL
  SELECT '74.125.0.0', '74.126.0.0' UNION ALL
  SELECT '209.85.128.0', '209.86.0.0' UNION ALL
  SELECT '216.239.32.0', '216.239.64.0' 
),
IPs AS (
  SELECT '64.233.160.2' AS IP UNION ALL
  SELECT '72.14.192.101'
)
SELECT *
FROM IPs AS i
JOIN Ranges AS r
ON ip2int(IP) BETWEEN ip2int(IP1) AND ip2int(IP2)  

输出为

IP              IP1             IP2  
72.14.192.101   72.14.192.0     72.15.0.0    
64.233.160.2    64.233.160.0    64.233.192.0     

这里有更多关于 NET functions and SQL UDF

的信息

作为我们 GDPR 处理的一部分,我们将 IP 范围数据集转换为每八位字节 3 个键值数据集(没有第 4 个),并且它在多个仓库中通过 SQL 在超过 10MM 的记录上运行良好。

基本上,而不是做:

FROM DATA
JOIN IP_RANGE ON DATA.IP_NUM BETWEEN IP_RANGE.IP_NUM_FROM AND IP_RANGE.IP_NUM_TO

我们测试了:

FROM DATA
LEFT JOIN IP_OCTET1 ON DATA.IP_OCTET1 = IP_OCTET1.IP_OCTET1
LEFT JOIN IP_OCTET2 ON DATA.IP_OCTET1 = IP_OCTET2.IP_OCTET1 AND DATA.IP_OCTET2 = IP_OCTET2.IP_OCTET2
LEFT JOIN IP_OCTET3 ON DATA.IP_OCTET1 = IP_OCTET3.IP_OCTET1 AND DATA.IP_OCTET2 = IP_OCTET3.IP_OCTET2 AND DATA.IP_OCTET3 = IP_OCTET3.IP_OCTET3
  • 我们发现我们的客户主要询问国家或美国各州,我们仅根据这些特定需求设计数据集。

您可以在我们最新的博客中阅读更多相关信息: https://cloudinary.com/blog/identifying_countries_by_ip_address_in_columnar_databases_through_sql

免责声明:我是这篇文章的作者。