Ниже приведен пример для BigQuery Standard SQL
#standardSQL
CREATE TEMP FUNCTION SubnetToRange(CIDR STRING)
RETURNS STRUCT<start_IP STRING, end_IP STRING>
LANGUAGE js AS """
var beg = CIDR.substr(CIDR,CIDR.indexOf('/'));
var end = beg;
var off = (1<<(32-parseInt(CIDR.substr(CIDR.indexOf('/')+1))))-1;
var sub = beg.split('.').map(function(a){return parseInt(a)});
var buf = new ArrayBuffer(4);
var i32 = new Uint32Array(buf);
i32[0] = (sub[0]<<24) + (sub[1]<<16) + (sub[2]<<8) + (sub[3]) + off;
var end = Array.apply([],new Uint8Array(buf)).reverse().join('.');
return {start_IP: beg, end_IP: end};
""";
SELECT e.*, t.* EXCEPT(start_IP, end_IP)
FROM `project.dataset.equipments` e,
(
SELECT s.*,
NET.IPV4_TO_INT64(NET.IP_FROM_STRING(start_IP)) AS start_IP,
NET.IPV4_TO_INT64(NET.IP_FROM_STRING(end_IP)) AS end_IP
FROM `project.dataset.subnets` s,
UNNEST([SubnetToRange(Subnet)])
) t
WHERE NET.IPV4_TO_INT64(NET.IP_FROM_STRING(IP)) BETWEEN start_IP AND end_IP
Вы можете протестировать, поиграть с выше, используя пример / фиктивные данные, как в примере ниже
#standardSQL
CREATE TEMP FUNCTION SubnetToRange(CIDR STRING)
RETURNS STRUCT<start_IP STRING, end_IP STRING>
LANGUAGE js AS """
var beg = CIDR.substr(CIDR,CIDR.indexOf('/'));
var end = beg;
var off = (1<<(32-parseInt(CIDR.substr(CIDR.indexOf('/')+1))))-1;
var sub = beg.split('.').map(function(a){return parseInt(a)});
var buf = new ArrayBuffer(4);
var i32 = new Uint32Array(buf);
i32[0] = (sub[0]<<24) + (sub[1]<<16) + (sub[2]<<8) + (sub[3]) + off;
var end = Array.apply([],new Uint8Array(buf)).reverse().join('.');
return {start_IP: beg, end_IP: end};
""";
WITH `project.dataset.subnets` AS (
SELECT 'HARRIS' Customer_ID, 1012 VLAN, '10.111.253.46/32' Subnet UNION ALL
SELECT 'HARRIS', 1012, '10.164.20.49/30' UNION ALL
SELECT 'HARRIS', 1012, '10.223.165.193/28' UNION ALL
SELECT '335553632', 3898, '10.98.0.49/28' UNION ALL
SELECT 'RINA', 1430, '10.64.9.0/27' UNION ALL
SELECT 'RINA', 3966, '10.98.1.13/32'
), `project.dataset.equipments` AS (
SELECT 'equipment A' equipment, '10.164.20.50' IP UNION ALL
SELECT 'equipment B', '10.64.9.0'
)
SELECT e.*, t.* EXCEPT(start_IP, end_IP)
FROM `project.dataset.equipments` e,
(
SELECT s.*,
NET.IPV4_TO_INT64(NET.IP_FROM_STRING(start_IP)) AS start_IP,
NET.IPV4_TO_INT64(NET.IP_FROM_STRING(end_IP)) AS end_IP
FROM `project.dataset.subnets` s,
UNNEST([SubnetToRange(Subnet)])
) t
WHERE NET.IPV4_TO_INT64(NET.IP_FROM_STRING(IP)) BETWEEN start_IP AND end_IP
с выводом
Row equipment IP Customer_ID VLAN Subnet
1 equipment A 10.164.20.50 HARRIS 1012 10.164.20.49/30
2 equipment B 10.64.9.0 RINA 1430 10.64.9.0/27