2015-04-17 4 views
0

У меня есть столбец из UK 10k в моей базе данных SQLite. Я хотел бы определить, какие из этих URI являются субдоменами одного и того же веб-сайта.Найти похожие записи в столбце SQL и ранжировать по частоте

Например, для данного набора ...

1. daiquiri.rum.cu 
2. mojito.rum.cu 
3. cubalibre.rum.cu 
4. americano.campari.it 
5. negroni.campari.it 
6. hemingway.com 

... Я хотел бы, чтобы выполнить запрос, который возвращает:

Website  | Occurrences 
---------------------------- 
rum.cu  |  3 
campari.it |  2 
hemingway.com |  1 

То есть, доменные имена/шаблоны, были сопоставлены, оценивались по количеству раз, когда они были найдены в базе данных.

Эвристика, которую я бы использовал: для каждого URI с доменами 3+ замените первый домен на «%» и выполните псевдокурс: COUNT (uris с сайта, где uris LIKE '% .remainderofmyuri').

Обратите внимание, что меня не очень беспокоит скорость выполнения (на самом деле, совсем нет). Количество записей находится в пределах 10k-100k.

+0

Откуда берутся rum.com? Это опечатка для rum.cu? (Или наоборот). –

+0

yep! Спасибо за комментарий. – bsuire

ответ

1

Единственная проблема - найти домен. Чтобы найти алгоритм, представьте себе ваши URL-адреса с дополнительной точкой впереди (например, «.negroni.campari.it» и «.hemingway.com»). Вы видите, что это всегда строка, которая появляется после секунд точки справа. Все, что нам нужно сделать, это найти это событие и вырезать часть строки. Однако, к сожалению, строковые функции SQLite довольно бедны. Нет функции, которая дает вам второе появление точки, даже если подсчет слева. Таким образом, агоризм отлично подходит для большинства dbms, но это не для SQLite. Нам нужен другой подход. (Я пишу это так или иначе, чтобы показать, как обычно подходить к проблеме.)

Вот решение SQLite. Разница между доменом и подобластями заключается в том, что в домене имеется ровно одна точка, тогда как поддомен имеет по меньшей мере, два. Поэтому, когда имеется более одной точки, мы должны удалить первую часть, включая первую точку, чтобы попасть в домен. Более того, мы хотим, чтобы это работало даже с поддоменами, такими как abc.def.geh.ijk.com, поэтому мы должны сделать это рекурсивно.

with recursive cte(uri) as 
(
    select uri from uris 
    union all 
    select substr(uri, instr(uri, '.') + 1) as uri from cte where instr(uri, '.') > 0 
) 
select uri, count(*) 
from cte 
where length(uri) = length(replace(uri,'.','')) + 1 -- domains only 
group by uri 
order by count(*) desc; 

Здесь мы генерируем «daiquiri.rum.cu» и «rum.cu» и «у.е.» от «daiquiri.rum.cu» и т.д. Таким образом, для каждого URI мы получаем домен (здесь «ром. cu ') и некоторые другие строки. Наконец, мы фильтруем LENGTH, чтобы получить те строки, которые имеют ровно одну точку - домены.Остальное - это группа и счет.

Вот скрипка SQL: http://sqlfiddle.com/#!5/c1f35/37.

+0

Спасибо, это очень помогло! Это, безусловно, правильный ответ, основанный на том, как я я должен был указать, что меня интересует только идентификация первых поддоменов (как в моих образцовых данных), но я смог понять это оттуда. Спасибо! – bsuire

0
select x.site, count(*) 
from mytable a 
inner join 
(
    select 'rum.cu' as site 
    union all select 'campari.it' 
    union all select 'hemingway.com' 
) x on a.url like '%' + x.site + '%' 
group by x.site -- EDIT I missed out the GROUP BY on the first go - sorry! 

(Это, как я хотел бы сделать это в SQL-сервере, не уверен, как SQLite отличается синтаксисом.)

«туЬаЫе» ваша таблица whuch имеет столбец URL, содержащий «мохито. rum.cu 'и т. д. Я не поставил «%». в подобном, потому что это пропустит hemmingway.com. Однако можно обойти, что с помощью этой строки вместо:

) x on a.url like '%.' + x.site + '%' or a.url = x.site 

Вы не можете нуждаться в fimal + «%» - я положил его в поймать URLs, как «hemingway.com/some-page.html. Если у вас нет таких URL-адресов, вы можете пропустить это.

EDIT для динамических имен

select x.site, count(*) 
from mytable a 
inner join 
(
    select distinct ltrim(url, instr(url, '.')) as site 
    from mytable 
    where url like '%.%.%' 
    union 
    select distinct url 
    from mytable 
    where url like '%.%' and url not like '%.%.%' 
) x on a.url like '%' + x.site + '%' 
group by x.site 

что-то подобное, что должны это сделать. Я не тестировал, что функция INSTR() верна. Вам может потребоваться добавить или вычесть 1 из смещения, которое оно генерирует, когда вы его проверяете. Возможно, это не самый быстрый запрос, но он должен работать.

+0

Спасибо! Возможно ли изменить запрос таким образом, чтобы имена домов были динамическими? В фактическом приложении я не знаю, какие домены имеют поддомены. – bsuire

+0

У вас есть URL-адрес, у которого есть страницы, например, например. hemmingway.com/somepage.html? –

+0

Нет, пути уже урезаны. – bsuire

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