我正在尝试进行统计跟踪。在我的数据库中,我存储引用的URL。我经常有类似以下内容的网址:
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和COUNT。基本上我想要的是返回如下:
trafficadbar 3
4acesmailer 5
目前,当我尝试进行GROUP BY时,它只适用于网址完全相同的情况。所以www.blah.com和blah.com是两个不同的结果,并且每个url变量更进一步?blah = 1& blahblah = 2作为另一个独特的群体,
我已经搜索了无数的解决方案,但它们似乎对所提出的问题非常具体,而且几乎所有解决方案似乎都显示了一些"非正则表达式"解决方法 - 这很好......如果我能找到一个可以应用的方法。
答案 0 :(得分: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
;
有:
如果需要,可以解决(在某种程度上)任何一个问题。
在行动SQL Fiddle中查看它(您的数据有所调整/扩展以涵盖更多案例)。
请评论是否需要调整/进一步详细说明。
答案 1 :(得分:0)
如果您只关心这两个值,那么这样的事情就可以了:
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
答案 2 :(得分:0)
我没有足够的技巧在SQL中可靠地完成这项工作;有太多可移动的部分:许多子域,可能有很多TLD(不仅仅是.com
),可能存在格式错误的域等...
我的方法:选择所有内容并在PHP中解析。
在下面的示例中,我假设网址位于urls
列中,并且您有一个date_added
列,其中包含每个网址添加到数据库时的日期时间。相应地调整您的查询。
选择过去30天内添加的所有网址:
SELECT `urls` FROM `myTable`
WHERE `date_added` >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
将所有结果放在$rows
数组中,然后处理该数组以生成所需的报告
$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,
]
您会注意到,与您不同,我保留了顶级域名(例如:.com
,.net
...),因为ebay.com
和ebay.ph
完全不同域。我建议不要将它们混合成一个结果。
答案 3 :(得分:0)
尽管@BeetleJuice的解决方案可行,并且可能比我选择的解决方案更可靠,但我选择了SQL解决方案
{{1}}
缺点是,它不是以http://w加注星标,而是加注http://random.sub.domain