Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Resumo dos registros de detalhes do MySQL correspondentes por intervalos de endereços IP - mySQL Jedi Knight necessário


Com sua estrutura de dados existente, você pode fazer a correspondência de strings da seguinte maneira (mas não é muito eficiente):
SELECT   schools.school, detail.filename, COUNT(*)
FROM     schools
    JOIN ipranges ON schools.id = ipranges.school_id
    JOIN detail   ON detail.ip_address LIKE REPLACE(ipranges.ip_range, 'x', '%')
WHERE    schools.consortium_id = ?
GROUP BY schools.school, detail.filename

Uma maneira melhor seria armazenar seus intervalos de IP como endereço de rede e comprimento de prefixo:
ALTER TABLE ipranges
  ADD COLUMN network INT UNSIGNED,
  ADD COLUMN prefix  TINYINT;
UPDATE ipranges SET
  network = INET_ATON(REPLACE(ip_range, 'x', 0)),
  prefix  = 32 - 8*(CHAR_LENGTH(ip_range) - CHAR_LENGTH(REPLACE(ip_range,'x',''));
ALTER TABLE ipranges
  DROP COLUMN ip_range;

ALTER TABLE detail
  ADD COLUMN ip_address_new INT UNSIGNED;
UPDATE detail SET
  ip_address_new = INET_ATON(ip_address);
ALTER TABLE detail
  DROP COLUMN ip_address,
  CHANGE ip_address_new ip_address INT UNSIGNED;

Então seria apenas um caso de realizar algumas comparações de bits:
SELECT   schools.school, detail.filename, COUNT(*)
FROM     schools
    JOIN ipranges ON schools.id = ipranges.school_id
    JOIN detail   ON detail.ip_address & ~((1 << 32 - ipranges.prefix) - 1)
                   = ipranges.network
WHERE    schools.consortium_id = ?
GROUP BY schools.school, detail.filename