sql >> Database >  >> RDS >> Mysql

Samenvatting van MySQL-detailrecords die overeenkomen met IP-adresbereiken - mySQL Jedi Knight vereist

Met je bestaande datastructuur zou je string-matching als volgt kunnen doen (maar het is niet erg efficiënt):

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

Een betere manier is om uw IP-bereiken op te slaan als netwerkadres en prefixlengte:

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;

Dan zou het slechts een kwestie zijn van het uitvoeren van enkele bitvergelijkingen:

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


  1. Gebruik COL_LENGTH() om de lengte van een kolom in SQL Server te krijgen

  2. URL herschrijven, ID vervangen door titel in queryreeks

  3. MariaDB JSON_ARRAY_INSERT() uitgelegd

  4. Meerdere rijen invoegen met PDO