Проверьте и сопоставьте IP-адрес с таблицей поиска su bnet с помощью SQL - PullRequest
4 голосов
/ 22 января 2020

У меня есть таблица, которая показывает IP-адреса, назначенные оборудованию, принадлежащему клиенту. Эта таблица используется для измерения активности и производительности пользователя и генерируется на регулярной основе. Я хотел бы сопоставить IP-адреса этих клиентов с идентификатором или именем клиента. Из-за размера и нескольких IP-адресов, которые могут быть назначены одному и тому же клиенту, мы должны использовать su bnet вместо отдельных IP-адресов.

Таблица отчета содержит поле IP-адреса и таблицу сопоставления su bnet это что-то вроде ниже.

+-------------+------+-------------------+
| Customer_ID | VLAN |      Subnet       |
+-------------+------+-------------------+
| HARRIS      | 1012 | 10.111.253.46/32  |
| HARRIS      | 1012 | 10.164.20.49/30   |
| HARRIS      | 1012 | 10.223.165.193/28 |
| HARRIS      | 1013 | 10.155.75.128/26  |
| HARRIS      | 1014 | 10.155.75.128/26  |
| HARRIS      | 1330 | 10.121.30.192/27  |
| HARRIS      | 1331 | 10.120.30.192/27  |
| HARRIS      | 1332 | 10.122.30.192/27  |
| HARRIS      | 3910 | 100.104.12.144/32 |
| HARRIS      | 3927 | 10.70.24.233/32   |
| HARRIS      | 3959 | 10.102.11.182/32  |
| HARRIS      | 3966 | 10.98.11.170/32   |
| STEPHANIE   | 1010 | 100.72.0.33/32    |
| STEPHANIE   | 3896 | 10.96.11.169/29   |
| JOE         | 1010 | 100.69.72.10/32   |
| NED         | 1010 | 100.72.255.2/32   |
| ESTHER      | 1010 | 100.72.255.66/32  |
| BEN         | 1010 | 100.72.255.30/32  |
| SHAWN       | 1010 | 100.72.254.230/32 |
| JACK        | 1010 | 1.1.1.7/32        |
| TONY        | 1010 | 100.72.255.242/32 |
| 335553339   | 1010 | 100.72.254.250/32 |
| 335553342   | 1010 | 100.72.254.186/32 |
| 335553343   | 1010 | 100.72.254.238/32 |
| 335553346   | 1010 | 100.72.255.182/32 |
| 335553347   | 1010 | 1.1.1.2/32        |
| 335553348   | 1010 | 100.72.255.82/32  |
| 335553349   | 1010 | 100.72.254.30/32  |
| 335553351   | 1010 | 1.1.1.1/32        |
| 335553352   | 1010 | 100.80.255.174/32 |
| 335553411   | 1010 | 100.72.255.18/32  |
| 335553412   | 1010 | 100.72.255.22/32  |
| 335553413   | 1010 | 100.72.255.253/32 |
| 335553414   | 1010 | 100.72.255.222/32 |
| 335553415   | 1010 | 100.72.255.202/32 |
| 335553416   | 1010 | 100.72.255.210/32 |
| 335553417   | 1010 | 100.72.255.10/32  |
| 335553418   | 1010 | 100.72.255.218/32 |
| 335553419   | 1010 | 100.72.255.206/32 |
| 335553420   | 1010 | 100.72.255.14/32  |
| 335553421   | 1010 | 100.72.255.114/32 |
| 335553431   | 1010 | 100.72.255.166/32 |
| 335553632   | 1010 | 100.72.4.176/32   |
| 335553632   | 3898 | 10.98.0.49/28     |
| RANDY       |  100 | 100.72.5.6/32     |
| RANDY       | 1012 | 10.111.230.41/32  |
| RANDY       | 1012 | 10.164.31.185/30  |
| RANDY       | 1012 | 10.228.5.1/28     |
| RANDY       | 1013 | 10.154.10.0/26    |
| RANDY       | 1014 | 10.154.10.0/26    |
| HASAN       | 1015 | 100.72.8.94/32    |
| HASAN       | 1015 | 100.73.13.56/32   |
| HASAN       | 3910 | 100.104.3.66/32   |
| HASAN       | 3927 | 10.70.7.157/32    |
| HASAN       | 3959 | 10.102.1.228/32   |
| HASAN       | 3966 | 10.98.2.68/32     |
| DICKY       |  100 | 100.72.10.203/32  |
| DICKY       | 3897 | 1.1.1.1/29        |
| RINA        |  100 | 100.73.2.12/32    |
| RINA        | 1430 | 10.64.9.0/27      |
| RINA        | 3910 | 100.104.2.12/32   |
| RINA        | 3927 | 10.70.2.155/32    |
| RINA        | 3959 | 10.102.1.15/32    |
| RINA        | 3959 | 10.104.8.24/29    |
| RINA        | 3966 | 10.98.1.13/32     |
+-------------+------+-------------------+

Как мне сопоставить адреса в моей динамической c таблице (проверьте, принадлежит ли она к какому su bnet) в запросе SQL, а затем добавить столбец (то есть соединение слева), показывающий имя связанного клиента?

Спасибо за помощь

Ответы [ 2 ]

2 голосов
/ 22 января 2020

Ниже приведен пример для 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         
0 голосов
/ 23 января 2020

Запрос, который ищет IP-адреса и подсети и опубликован в:

# replace with your source of IP addresses

WITH source_of_ip_addresses AS (
  SELECT REGEXP_REPLACE(contributor_ip, 'xxx', '0')  ip, COUNT(*) c
  FROM `publicdata.samples.wikipedia`
  WHERE contributor_ip IS NOT null  
  GROUP BY 1
)

SELECT country_name, SUM(c) c
FROM (
  SELECT ip, country_name, c
  FROM (
    SELECT *, NET.SAFE_IP_FROM_STRING(ip) & NET.IP_NET_MASK(4, mask) network_bin
    FROM source_of_ip_addresses, UNNEST(GENERATE_ARRAY(9,32)) mask
    WHERE BYTE_LENGTH(NET.SAFE_IP_FROM_STRING(ip)) = 4
  )
  JOIN `fh-bigquery.geocode.201806_geolite2_city_ipv4_locs`  
  USING (network_bin, mask)
)
GROUP BY 1
ORDER BY 2 DESC

Математика здесь довольно быстро и не требует JS UDF. Просто замените country_name на customer_name.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...