sam*_*and 2 sql t-sql haproxy referer sql-server-2016
我正在尝试将事件归因于流量日志中的源.对于任何半精明的技术营销人员或网站管理员而言,这似乎是相当基本的领域,但我已经用Google搜索了一下,而且令人惊讶的是,似乎没有人覆盖这一点.
背景:我使用T-SQL,我们正在SQL Server上运行2016年我的事件日志(HAProxy的)是这个样子,哪里RefererHost是'%mysite%'内部推荐,但也可以是其他任何外部推荐(入口).
User Agent || IP || RefererHost || Event || CreationDate
------------------------------------------------------------------------------
qwertyuiop || 99.99.99.9 || google.com || Home/View || 2015-05-29 00:00:25
------------------------------------------------------------------------------
qwertyuiop || 99.99.99.9 || mysite/x || Home/View || 2015-05-29 00:00:27
------------------------------------------------------------------------------
abcdefghij || 11.11.11.1 || yahoo.com || Home/View || 2015-05-29 00:00:49
------------------------------------------------------------------------------
qwertyuiop || 99.99.99.9 || mysite/y || Submit || 2015-05-29 00:01:28
------------------------------------------------------------------------------
abcdefghij || 11.11.11.1 || mysite/p || Photo/View || 2015-05-29 00:02:04
------------------------------------------------------------------------------
abcdefghij || 11.11.11.1 || mysite/n || Submit || 2015-05-29 00:02:09
Run Code Online (Sandbox Code Playgroud)
目标:我试图将所有Submit事件与他们的入口联系起来.聚合,结果看起来像这样:
RefererHost || SubmitCount ||
------------------------------
google.com || 1 ||
yahoo.com || 1 ||
Run Code Online (Sandbox Code Playgroud)
复杂因素:但这是一个非常简单的例子.事实上,每个用户可以每个时段访问多次,并且Submit每次访问(会话)可以多次访问.此外,用户可以在入口后长时间闲置:a Submit可以在入口后数小时发生.
所以我认为我要做的是选择所有CreationDatesEvent = Submit,和Users(IP + UA校验和),然后找到最近的前一个事件= RefererHost不是'%mysite%',并存储它...某个与之相关的地方Submit事件.然后我可以做一些Submit事件,分组RefererHost来得到我正在寻找的东西.
这个方法对我来说有些意义,但我不知道如何编写一个"回顾"查找最近的先前引用的查询.另外,我不确定单独的SQL是否可以在没有操作超时的情况下处理这个问题.而且我不确定我是否错过了一个边缘案例.以前有人做过这样的事吗?
小智 5
如果您正在使用具有窗口函数的数据库,则可以使用相当短的查询来执行此操作.如果您想在实时数据上修改此问题,您还可以查看此查询的一个有效示例(带有一些虚拟数据):https://modeanalytics.com/benn/reports/9f72b24dce58/query
其中的每个步骤都作为公用表表达式进行分解.虽然这使得描述更容易,但如果该样式更符合您的要求,则可以将查询编写为一系列子查询.
第1步:我做了你的桌子.
WITH event_table AS (
SELECT user_id AS dummy_ip,
occurred_at,
location AS dummy_referer,
event_name
FROM tutorial.playbook_events
)
Run Code Online (Sandbox Code Playgroud)
我所拥有的示例数据并未完全映射到您的示例,但这会创建一个大致相同的表.我映射user_id到,ip_address因为这两个字段在概念上是相同的.location并且referer完全没有任何关系,但它们都是与每个事件相关的事件属性.location我的数据中有一个字段,所以我就去了.我猜想,它可以像物理引用者一样.
第2步:确定自上次事件以来的时间.
with_last_event AS (
SELECT *,
LAG(occurred_at,1) OVER (PARTITION BY dummy_ip ORDER BY occurred_at) AS last_event
FROM event_table
)
Run Code Online (Sandbox Code Playgroud)
此处的LAG函数查找该IP上的最后一个事件的时间.如果没有最后一个事件,则为空.
第3步:查找哪些事件标记新会话的开始.
with_new_session_flag AS (
SELECT *,
CASE WHEN EXTRACT('EPOCH' FROM occurred_at) - EXTRACT('EPOCH' FROM last_event) >= (60 * 10) OR last_event IS NULL
THEN 1 ELSE 0 END AS is_new_session,
CASE WHEN EXTRACT('EPOCH' FROM occurred_at) - EXTRACT('EPOCH' FROM last_event) >= (60 * 10) OR last_event IS NULL
THEN dummy_referer ELSE NULL END AS first_referer
FROM with_last_event
)
Run Code Online (Sandbox Code Playgroud)
大多数平台将新会话定义为一段时间不活动后的操作.第一个案例陈述通过查看自上次事件以来已经过了多长时间来做到这一点.如果它比您选择的时间长(在这种情况下,60秒*10,那么10分钟),那么该事件将被标记为新会话中的第一个事件.它被标记为1; 非首事件标记为0.
第二个case语句查找相同的事件,但不是用1标记该事件将其标记为新会话,而是返回referer.如果它不是新会话,则返回null.
第4步:创建会话ID.
with_session_ids AS (
SELECT *,
SUM(is_new_session) OVER (ORDER BY dummy_ip, occurred_at) AS global_session_id,
SUM(is_new_session) OVER (PARTITION BY dummy_ip ORDER BY occurred_at) AS user_session_id
FROM with_new_session_flag
)
Run Code Online (Sandbox Code Playgroud)
这些窗口函数产生会话标志的运行总数(当它是新会话时为1,而当不是新会话时为0).结果是一个列在会话未更改时保持不变,并在每次新会话开始时递增1.根据您对此窗口功能进行分区和排序的方式,您可以创建对该用户而言唯一且全局唯一的会话ID.
第5步:找到原始会话引用程序.
with_session_referer AS (
SELECT *,
MAX(first_referer) OVER (PARTITION BY global_session_id) AS session_referer
FROM with_session_ids
)
Run Code Online (Sandbox Code Playgroud)
这最后一个窗口函数查找的MAX价值first_referer为global_session_id.由于该列是null针对除该会话的第一个事件之外的每个值,因此将返回该first_referer会话中每个事件的该会话.
第6步:计算一些东西.
SELECT session_referer,
COUNT(1) AS total_events,
COUNT(DISTINCT global_session_id) AS distinct_sessions,
COUNT(DISTINCT dummy_ip) AS distinct_ips
FROM with_session_referer
WHERE event_name = 'send_message'
GROUP BY 1
Run Code Online (Sandbox Code Playgroud)
最后一步很简单 - 只将事件过滤到您关心的事件(Submit在您的示例中).然后计算事件数session_referer,这是该事件发生的会话的第一个引用者.通过计数global_session_id和dummy_ip,您还可以找到会话如何具有该事件,以及记录该事件的不同IP数量.
| 归档时间: |
|
| 查看次数: |
122 次 |
| 最近记录: |