MySQL的路径报告


Path report from MySQL

我有一个数据库表,它跟踪通过php脚本激发的所有页面视图。表格如下:

  • rowid(AI)
  • user_id
  • 页面url
  • 访问者_ip
  • 会话id

我希望能够查询我的表,以"显示访问者在一个会话内到达X页面的路径(最多5页)"。输出将是一个表,每列中都有一个URL,因此路径按照他们访问具有相同session_id的页面的顺序从左到右,以某个页面结尾。

有线索吗?我一直在寻找一个报告工具来帮助我构建这些细分市场,但我没有想出任何东西,所以我想看看是否有一种方法可以直接查询它。我希望避免使用其他工具进行收集,如果可以的话,只查询我的数据库。

这样的东西能给你想要的东西吗(警告-未经测试):

select group_concat(page_url order by rowid separator '->'),session_id 
from pageviews group by session_id

一个想法是在选择列表中使用相关的子查询。

如果我理解规范,那么查询的自变量(参数)将是一个特定的`page_url`,在规范中给出为"X"。

外部查询将检索该page_url的行。SELECT列表中的子查询将获得会话中的前一个page_url。(我们看不到日期时间/时间戳,因此我们需要依赖于后续页面视图的"rowid"值的增加(即,之前的页面视图将具有"较低"的"row_id"值)。

类似这样的东西:

SELECT ( SELECT p5.page_url
           FROM pageviews p5
          WHERE p5.session_id = t.session_id
            AND p5.rowid < t.rowid
          ORDER BY p5.rowid DESC
          LIMIT 4,1
       ) AS back_5_page_url
     , ( SELECT p4.page_url 
           FROM pageviews p4
          WHERE p4.session_id = t.session_id
            AND p4.rowid      < t.rowid
          ORDER BY p4.rowid DESC
         LIMIT 3,1
      ) AS back_4_page_url
     , ( SELECT p3.page_url
           FROM pageviews p3
          WHERE p3.session_id = t.session_id
            AND p3.rowid      < t.rowid
          ORDER BY p3.rowid DESC
          LIMIT 2,1
       ) AS back_3_page_url
     , ( SELECT p2.page_url
           FROM pageviews p2
          WHERE p2.session_id = t.session_id
            AND p2.rowid      < t.rowid
          ORDER BY p2.rowid DESC
          LIMIT 1,1
       ) AS back_2_page_url
     , ( SELECT p1.page_url
           FROM pageviews p5
          WHERE p1.session_id = t.session_id
            AND p1.rowid      < t.rowid
          ORDER BY p1.rowid DESC
          LIMIT 0,1
       ) AS back_1_page_url
     , t.page_url
     , t.session_id
     , t.row_id
  FROM pageviews t
 WHERE t.page_url = 'X'

这些子查询将针对外部查询返回的每个行执行,因此这可能会影响性能。如果没有合适的索引,它也会吃掉我们的午餐盒。

对于子查询,我们需要一个索引。。。

页面浏览量(session_id、row_id、page_url)

外部查询将受益于索引。。。

页面浏览量(page_url、row_id、session_id)


作为一种不同方法的开始,如果我们获得每个page_url的路径,而不仅仅是一个特定的路径。。。

SET group_concat_max_len = 524288 ;
SELECT t.session_id
     , t.page_url
     , SUBSTRING_INDEX(
         GROUP_CONCAT(t.page_url SEPARATOR ''t' ORDER BY t.rowid DESC)
       ,''t',6) AS `last_5_pages`
  FROM pageviews t
 GROUP
    BY t.session_id
     , t.page_url
HAVING t.page_url = 'X'

这假设page_url将不包含制表符(0x09)字符。

last_5_pages列将是一个由选项卡分隔的page_url列表,首先是最近的页面视图,然后是以前查看过的page_url

将这些拆分为单独的列将需要更多的工作,将该查询包装在内联视图中,并结合SUBSTRING_INDEX(可能是REVERSE)和一个计算列表中page_url数量的函数。。。在SQL中这样做有点令人讨厌。如果我采用这种方法,我更愿意处理从客户端的选项卡分隔列表中解析出page_url。

以下是我最终所做的事情-效果很好。

<?php
require_once 'init.php';
// ----------------- PAGE PATH REPORT
$html = "<table>";
$html .= "<tr><th align='left'>PAGE PATHS HITTING GOAL.PHP</th></tr>";
$paths = array();
$sql = "SELECT cookie_uid, page_url FROM pageviews ORDER BY rowid";
$result = mysqli_query($conn, $sql);
$got_rows = mysqli_num_rows($result);
if ($got_rows) {
    while ($row = mysqli_fetch_array($result)) {
        // Create an array for the cookie_uid if it doesn't exist yet
        if ( ! array_key_exists($row['cookie_uid'], $paths) || ! is_array($paths[$row['cookie_uid']])) {
            $paths[$row['cookie_uid']] = [];
        }
        // Add to the array now that we know it exists
        array_push($paths[$row['cookie_uid']], $row['page_url']);
    }
    foreach ($paths as $session => $page) {
        $html .= "<tr>";
        $html .= '<td>' . implode('  --->   ', $page) . "</td>";
        $html .= "</tr>";
    }
} else {
    $html .= '<td colspan="2">No results</td>' . "";
}
$html .= "</table>";
echo $html;
if (!mysqli_query($conn,$sql))  {
    die('Error: ' . mysqli_error($conn));
}
// ----------------- ALL PAGES REPORT
echo "</br></br>";
echo "<tbody><table>";
echo "<tr><th align='left'>UNIQUE PAGES</th></tr>";
$sql = "SELECT distinct page_url FROM pageviews";
$allpages = mysqli_query($conn, $sql);
foreach ($allpages as $page){
    echo "<tr>";
    echo "<td>" . $page['page_url'] . "</td>";
    echo "</tr>";
}
echo "</tbody></table>";
mysqli_close($conn);
error_reporting(E_ALL);
?>

这给了我这个:

/analytics/testpage.php--->/analytics/testpage2.php--->/aanalytics/goor.php