2016-07-23 26 views
2

我正在嘗試做統計跟蹤。在我的數據庫中,我存儲了引用URL。我經常有網址的類似於下面:MYSQL:Group按正則表達式

http://www2.trafficadbar.com/__a4w4 
http://trafficadbar.com/__a4w4 
http://www.trafficadbar.com/__a4w4 
http://4acesmailer.com/credit_click.php?userid=2472&openkey=gbyp2vcm 
http://4acesmailer.com/credit_click.php?userid=2714&openkey=gbyp2vcm 
http://4acesmailer.com/credit_click.php?userid=2723&openkey=gbyp2vcm 
http://4acesmailer.com/credit_click.php?userid=3245&openkey=gbyp2vcm 
http://4acesmailer.com/credit_click.php?userid=3259&openkey=gbyp2vcm 

我想知道我會怎麼做一個GROUP BY和指望一個正則表達式。基本上我想要的是如下返回:

trafficadbar 3 
4acesmailer 5 

目前,當我嘗試做一個GROUP BY它只能URL的地方是完全相同的。所以www.blah.com和blah.com是兩個不同的結果,並進一步每個url變量?blahblah = 2作爲又一個獨特的組,

我已經搜索了無數的解決方案,但他們似乎主要對所問的問題非常具體,幾乎所有的問題都顯示出一些「非正則表達式」的解決方法 - 如果我能找到一種我可以應用的方法,那很好。

+0

我不會經常這樣說,但你可能會選擇全部然後用PHP解析它。 – AbraCadaver

+0

我同意@AbraCadaver。我會在PHP中進行解析。 – BeetleJuice

回答

1

要從主機名檢索緊接在頂級域之前的部分,您可以工作:

SELECT 
    REVERSE(SUBSTRING(SUBSTRING_INDEX(rev_hostname, '.', 2), 
      LOCATE('.', rev_hostname) + 1) 
     ) domain 
    , COUNT(id) hits 
FROM (
    SELECT 
    id 
    , CONCAT(REVERSE(SUBSTRING_INDEX(SUBSTRING(referring_site, 8), 
            '/', 1)), '.') rev_hostname 
    FROM TestData 
) T 
GROUP BY domain 
; 

它:

  • 依賴於所有referring_site s的HTTP來開始://,並
  • 會失敗 - 因爲它的立場 - 對,例如4acesmailer。 co.uk

如果需要,任何一個都可以解決(某種程度上)。

看到它在行動SQL Fiddle(你的數據有些調整/擴展到覆蓋更多的情況)。

請評論如果和因爲這需要調整/進一步的細節。

0

如果你只關心那些2倍的值,像這樣的工作:

select case when yourcolumn like '%trafficadbar%' then 'trafficadbar' 
      when yourcolumn like '%4acesmailer%' then '4acesmailer' 
     end, 
    count(*) 
from yourtable 
group by 1 

編輯,給出你的意見,這可能是多一點動態且相對容易延伸:

select 
    replace(replace(replace(
    left(yourcolumn, locate('.com', yourcolumn) - 1), 
    'http://', ''), 
    'www.', ''), 
    'www2.', ''), 
    count(*) 
from yourtable 
group by 1 
+1

我很確定這些都是例子,他們並不知道所有的域名。 – AbraCadaver

+0

@AbraCadaver - 好的一點,可能不完全清楚,如果OP正在搜索特定的域名或想要以某種方式聚合相似的域名。不要以爲後者是單獨使用sql的可能性... – sgeddes

+0

在我的文章中,這個詞「類似」,當然是打算說我不是專門搜索那些 - 那很容易:) – Bruce

0

我沒有足夠的技術在SQL這樣做可靠的一切;有太多的運動部件:大量的子域,大量頂級域名的可能(不只是.com),畸形域可能等等

我的方法:選擇一切,在PHP解析。

在下面的示例中,我假設網址位於urls列中,並且您有一個date_added列,其中包含每個網址添加到數據庫的日期時間。相應地調整您的查詢。

選擇在最近30天添加的所有URL:在$rows陣列

SELECT `urls` FROM `myTable` 
WHERE `date_added` >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) 

將所有結果,然後處理該生成你想要

$rows = [...];//Associative array of all rows returned by the query above 
$results = []; //will hold aggregate counts 

foreach($rows as $row){ 
    $host = parse_url($row['urls'],PHP_URL_HOST); //eg: www2.trafficadbar.com 
    $matches = []; 

    //find top level domain or skip to next row 
    if(!preg_match('/[^\.]*\.[^\.]+$/',$host,$matches)) continue;   

    $domain = $matches[0]; //eg: trafficadbar.com 

    //increment the count for this domain in results 
    if(!isset($results[$domain])) $results[$domain]=0; 
    $results[$domain]++; 
} 

的報告用你給的輸入在OP中,$results將是:

[ 
    'trafficadbar.com' => 3, 
    '4acesmailer.com' => 5, 
] 

你'我會保留TLD(例如:.com.net ...),因爲ebay.comebay.ph是完全不同的域。我建議不要把它們混合成一個結果。

Live demo

+0

好的。但只是添加到循環中的數組,然後使用'array_count values()' – AbraCadaver

+0

我不認爲這會更快,因爲您將遍歷數組兩次(首先所有網址添加域,然後所有結果來計算值),當我只做一次。 – BeetleJuice

0

雖然從@BeetleJuice的解決方案會工作,並可能更可靠,比我選擇的解決方案,我選擇了一個SQL解決方案

SELECT 
    CASE WHEN SUBSTRING(referring_site, 1, 8) = 'http://w' 
     THEN SUBSTRING_INDEX((SUBSTRING_INDEX(referring_site, '.', 2)), '.', -1) 
     ELSE SUBSTRING_INDEX((SUBSTRING_INDEX(referring_site, '.', 1)), '://', -1) 
    END 
AS domain 
FROM 
.... 

缺點是當它不出演與http://w,而是一些http://random.sub.domain

+0

如果有人有更好的純粹的mysql解決方案,那是我真正想要的。最終我想要做的是計算「」的數量。 between://和/然後如果2做第一個substring_index否則做第二個。我只是不知道如何獲得和適用於「。」。 – Bruce

+0

(i)重新組合是否正確:您想要頂級域名(** com **,** org **等)之前的部分? (根據點數來判斷可能是誤導性的:你想從** abc.def.ghi.com **得到什麼?)(ii)總是開始** http **? – Abecee