MYSQL суммировать значения по двум столбцам в зависимости от значений, сгруппированных из других столбцов - PullRequest
0 голосов
/ 10 февраля 2020

У меня есть сеть, созданная MYSQL таблица со следующими полями:

IP_SRC, IP_DST, BYTES_IN, BYTES_OUT, START_TIME, STOP_TIME
1.1.1.1 8.8.8.8 1080      540        1580684018  1580684100
8.8.4.4 1.1.1.1 2000      4000       1580597618  1580597800

Значения TIME являются тиками времени эпохи, и каждая запись в основном представляет собой один сеанс TCP. IP-адреса хранятся как «int (10) unsigned», т.е. я использую INET_NTOA, чтобы добраться до строки «1.1.1.1». START_TIME, STOP_TIME, IN_BYTES и OUT_BYTES также являются «int (10) unsigned»

Я хотел бы сформулировать запрос (или процедуру), чтобы вернуть таблицу со следующими полями:

IP_ADDR, TotalOutBytes
1.1.1.1      12345
8.8.8.8      83747
8.8.4.4      2389

где для данного IP_ADDR, скажем, 1.1.1.1, TotalOutBytes представляет собой сумму IN_BYTES, когда IP_DST равен 1.1.1.1, и OUT_BYTES, когда IP_SR C равен 1.1.1.1. Я хотел бы, чтобы все IP_SR C и IP_DST из исходной таблицы были учтены в новой таблице. Я также хотел бы, чтобы эти данные собирались за последние 24 часа.

Вот то, что у меня есть, это работает для суммирования только IN_BYTES (и сообщения в мегабайтах в порядке убывания для итогов более 50 МБ):

select IP_ADDR, format(MBx/1048576,0) AS TotalOutBytes from
  (select inet_ntoa(IP_DST_ADDR) AS IP_ADDR, sum(IN_BYTES) MBx from 
    (select IP_DST_ADDR, IN_BYTES from flowsv4 
        where FIRST_SWITCHED BETWEEN UNIX_TIMESTAMP(NOW() - INTERVAL 1 DAY)
            AND UNIX_TIMESTAMP(NOW())) total
GROUP BY IP_DST_ADDR) NEW WHERE MBx > 50*1048576 ORDER BY MBx DESC;

Ответы [ 2 ]

0 голосов
/ 10 февраля 2020

Ваш существующий запрос может быть значительно упрощен путем удаления ненужных вложений.

Для суммирования другого поля в соответствии со столбцом, содержащим соответствующую ip, вы можете использовать выражение case:

select 
    inet_ntoa(ip_dst_addr) as ip_addr, 
    format(
        sum(case '1.1.1.1'
            when ip_dst then in_bytes 
            when ip_src then out_bytes
        end) / 1048576,
        0
    ) totalBytes
from flowsv4 
where first_switched 
    between unix_timestamp(now() - interval 1 day) and unix_timestamp(now())
group by ip_dst_addr
having totalBytes > 50
order by totalBytes desc

Обратите внимание, что сортировка немного менее точна тот, что в исходном запросе, поскольку он использует форматированное значение Мб. Если это действительно имеет значение для вас, вы можете повторить условное sum() в предложении order by.

0 голосов
/ 10 февраля 2020

Вы можете использовать UNION для создания производной таблицы из BYTES_IN, когда IP_ADDR является пунктом назначения, и BYTES_OUT, когда IP_ADDR является источником, а затем SUM байтов над этой таблицей:

SELECT IP_ADDR, SUM(BYTES) AS TotalOutBytes
FROM (
  SELECT IP_SRC AS IP_ADDR, BYTES_OUT AS BYTES
  FROM flowsv4
  UNION ALL
  SELECT IP_DST, BYTES_IN
  FROM flowsv4
) f
GROUP BY IP_ADDR

Демонстрация по SQLFiddle

...