library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))
Помните, что дюйм/с не является текстовым адресом, а числовым идентификатором. У меня есть аналогичная ситуация (мы делаем геоIP поиски), и если Вы храните все свои IP-адреса как целые числа (например, мой IP-адрес 192.115.22.33, таким образом, он хранится как 3228767777), тогда Вы можете дюйм/с поиска легко при помощи операторов сдвига вправо.
оборотная сторона всех этих типов поисков - то, что Вы не можете извлечь выгоду из индексов, и необходимо сделать полное сканирование таблицы каждый раз, когда Вы делаете поиск. Вышеупомянутая схема может быть улучшена путем хранения обоих сетевой IP-адрес сети CIDR (начало диапазона) и широковещательный адрес (конец диапазона), так например, для хранения 192.168.1.0/24, можно сохранить два столбца:
network broadcast
3232235776, 3232236031
И затем Вы можете для соответствия ему, Вы просто делаете
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
, Это позволило бы Вам сохранить сети CIDR в базе данных и соответствовать им против IP-адресов быстро и эффективно путем использования в своих интересах быстрых числовых индексов.
Примечание из обсуждения ниже :
MySQL 5.0 включает расположенную оптимизацию запросов, названную" , индексное слияние пересекается ", который позволяет ускорять такие запросы (и избегать полных сканирований таблицы), пока:
(network, broadcast)
. COUNT(*)
, но не верно для SELECT * ... LIMIT 1
. MySQL 5.6 включает оптимизацию под названием MRR, который также ускорил бы полное извлечение строки, но это вне объема этого ответа.
Hmmm. Вы могли создать таблицу cidr масок, присоединиться к ней и затем выдержать сравнение, IP внес (&
в MySQL) с маской с блоком запрета ipaddress. Это сделало бы то, что Вы хотите?
, Если Вы не хотите создавать таблицу маски, Вы могли бы вычислить маску как -1 << (x-cidr)
с x = 64
или 32
зависящий.
Для IPv4
, можно использовать:
SET @length = 4;
SELECT INET_NTOA(ipaddr), INET_NTOA(searchaddr), INET_NTOA(mask)
FROM (
SELECT
(1 << (@length * 8)) - 1 & ~((1 << (@length * 8 - cidr)) - 1) AS mask,
CAST(CONV(SUBSTR(HEX(ipaddr), 1, @length * 2), 16, 10) AS DECIMAL(20)) AS ipaddr,
CAST(CONV(SUBSTR(HEX(@myaddr), 1, @length * 2), 16, 10) AS DECIMAL(20)) AS searchaddr
FROM ip
) ipo
WHERE ipaddr & mask = searchaddr & mask