Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php MYSQL:按正则表达式模式分组_Php_Mysql_Regex_Pdo - Fatal编程技术网

Php MYSQL:按正则表达式模式分组

Php MYSQL:按正则表达式模式分组,php,mysql,regex,pdo,Php,Mysql,Regex,Pdo,我正在尝试做统计跟踪。在我的数据库中,我存储引用URL。我经常有类似以下内容的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_c

我正在尝试做统计跟踪。在我的数据库中,我存储引用URL。我经常有类似以下内容的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
我想知道我将如何做一个分组并依靠正则表达式模式。基本上我想要的是:

trafficadbar 3
4acesmailer 5 
目前,当我尝试通过它创建一个组时,它只在url完全相同的情况下工作。所以www.blah.com和blah.com是两个不同的结果,而且每个url变量?blah=1&blahblah=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

我没有足够的技能用SQL可靠地完成这一切;有太多的活动部分:很多子域,可能有很多TLD,不仅仅是.com,可能有格式错误的域等等

我的方法是:选择所有内容并用PHP进行解析

在下面的示例中,我假设url位于url列中,并且您有一个date_added列,其中包含每个url添加到DB的日期时间。相应地调整您的查询

选择最近30天内添加的所有URL:

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中提供的输入,$结果将是:

您会注意到,与您不同,我保留了TLD,例如:.com、.net。。。因为ebay.com和ebay.ph是完全不同的域名。我建议不要把它们混成一个结果


虽然@甲壳虫果汁的解决方案会起作用,而且可能比我选择的解决方案更可靠,但我选择了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 
....

缺点是当它不是以一个而不是一些

开始从主机名中检索顶级域前面的部分时,您可以:

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
;
它:

依赖于所有引用站点以http:///开始,以及 将失败——正如它所代表的那样——例如,4acesmailer.co.uk。 如果需要,可以在某种程度上解决这两个问题

将数据稍作调整/扩展以涵盖更多情况,并将其付诸实施


如果这需要调整/进一步的细节,请发表评论。

我不经常这样说,但您最好选择all,然后用PHP对其进行解析。我同意@AbraCadaver。我会用PHP进行解析。我很确定这些都是示例,他们并不知道所有的域名。@Abracadver-好的一点是,可能不完全清楚OP是在搜索特定的域还是希望以某种方式聚合类似的域。不要认为单凭sql就可以实现后者……我在帖子中提到的“相似”一词,肯定是想说我并不是专门在搜索这些东西——这很容易:@Bruce——很公平,单凭sql这一点并不微不足道。请查看编辑以获得潜在的工作解决方案…@sgedes这可能是什么?好的。但只需在循环中添加到数组,然后使用数组_count values我不认为这会更快,因为您将遍历数组两次,首先遍历所有URL以添加域,然后遍历所有结果以计算值,而我只执行一次。如果有人有更好的纯mysql解决方案,这就是我真正想要的。最终我想做的是数一数。在://和/之间,如果2执行第一个子字符串,则执行第二个子字符串。我只是不知道如何获得和应用一个适当的计数。我重新措辞是否正确:您想要顶级域com、org等之前的部分。?根据点的数量判断可能会产生误导:您希望从abc.def.ghi.com获得什么?我总是启动http?
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
;