2016-09-13 5 views
1

У меня есть очень простая таблица (LOG), содержащая атрибуты MAC_ADDR, IP_SRC, IP_DST, URL, PROTOCOL. Я хочу, чтобы первые n строк, содержащих IP_SRC, URL, #OfOccurrences упорядочивались путем уменьшения #OFOccurrences для каждого IP_SRC в моей таблице, когда PROTOCOL = 'DNS'.SQL: максимальное количество событий для каждого значения

Чтобы быть яснее, я хочу, чтобы иметь возможность перечислить первые n наиболее посещаемых страниц для каждого IP_SRC в моей таблице.

я могу получить самый посещаемый URL для каждого IP_SRC, как это:

select ip_src,url,cnt 
from (
    select ip_src,url,count(*) as cnt,protocol 
    from log as b group by ip_src,url order by ip_src,cnt desc 
) as c 
where cnt>=(select MAX(cpt) 
      from (select count(*) as cpt from log as b 
      where c.ip_src==b.ip_src group by ip_src,url) 
      ) 
     and protocol='DNS'; 

Однако это решение, очевидно, не оптимизирован.

Вот более практический код (для наиболее посещаемого URL для каждого IP_SRC):

select ip_src,url,cnt 
from (select ip_src,url,count(*) as cnt 
     from log where protocol='DNS' 
     group by ip_src,url 
     order by ip_src,cnt asc) 
group by ip_src; 

Этот второй вариант намного больше быстрее! Тем не менее, я хочу, чтобы n самых посещаемых страниц для каждого IP_SRC, и я не могу понять, как это сделать.

Благодарим за помощь.

+0

Tag СУБД вы используете. (Некоторый недопустимый SQL там ...) – jarlh

+0

@jarlh Спасибо, действительно, это _sqlite_. – thefiercerabbit

ответ

0

Наконец, используя временную таблицу, я мог бы получить то, что хотел.

--First create a temp table of occurences 
CREATE TEMPORARY TABLE TEMP1 AS 
SELECT ip_src,url,count(*) AS cnt 
FROM LOG 
WHERE protocol='DNS' 
GROUP BY ip_src,url 
ORDER BY ip_src,cnt,url DESC; 
--Then use a classic limit per group query 
SELECT T1.ip_src,T1.url,T1.cnt 
FROM TEMP1 AS T1 
WHERE T1.url in (
     SELECT T2.url 
     FROM TEMP1 AS T2 
     WHERE T2.ip_src=T1.ip_src and T2.cnt>=T1.cnt 
     ORDER BY T2.cnt DESC 
     LIMIT 3 --Or whatever you want it to be 
) 
ORDER BY T1.ip_src ASC,T1.cnt DESC; 

Если кто-то знает, как сделать то же самое без необходимости использования временной таблицы (или объяснить мне, почему таблица температуры является хорошим решением), пожалуйста, выразить себя.

0
select x.ip_src, x.url, x.cnt 
from (select ip_src,url,count(*) as cnt 
     from log where protocol='DNS' 
     group by ip_src,url 
     order by ip_src, count(*) desc) AS x 
group by x.ip_src; 

Вы можете попробовать это?

+0

Он не улучшает мой второй код, а 'desc' должен быть' asc', чтобы собрать самые высокие значения. Все дело в том, чтобы иметь столько ответов на IP_SRC, сколько я хочу. Здесь у меня только самая высокая ценность ... Возможно, я был недостаточно ясен. – thefiercerabbit

1

Используйте common table expression:

WITH Temp1 AS (
    SELECT ip_src, url, count(*) AS cnt 
    FROM Log 
    WHERE protocol = 'DNS' 
    GROUP BY ip_src, url 
) 
SELECT ip_src, url, cnt 
FROM Temp1 AS T1 
WHERE url IN (
    SELECT url 
    FROM Temp1 AS T2 
    WHERE T2.ip_src = T1.ip_src 
    AND T2.cnt >= T1.cnt 
    ORDER BY cnt DESC 
    LIMIT 3 -- or whatever you want it to be 
) 
ORDER BY ip_src ASC, cnt DESC; 
+0

Собственно, это не так эффективно, как временная таблица. Моя таблица довольно маленькая (менее 2000 записей), и ваше решение занимает более 31 секунды (RasperryPi 2). Чтобы сравнить, с временной таблицей требуется всего 2 секунды! – thefiercerabbit

Смежные вопросы