如何提取在 2020 年 1 月至少访问过两次但未进行交易的所有 visitor_id 的列表(在他们 1 月的任何一次访问中)

Posted

技术标签:

【中文标题】如何提取在 2020 年 1 月至少访问过两次但未进行交易的所有 visitor_id 的列表(在他们 1 月的任何一次访问中)【英文标题】:How to pull a list of all visitor_ids that have visited at least twice in January 2020, but did not transact (in ANY of their January visits) 【发布时间】:2020-05-18 00:58:58 【问题描述】:

表格:

    会话

    session_ts visitor_id 垂直 session_id

    交易

    session_ts session_id rev_bucket 收入

目前有以下查询(使用 SQLite):

SELECT
   visitor_id,
   session_id,
   running_total
FROM 
  (
    SELECT
      s.visitor_id,
      s.session_id,
      t.revenue,
      ROW_NUMBER() OVER(PARTITION BY s.visitor_id ORDER BY t.session_ts) as row_num,
      SUM(revenue) OVER(PARTITION BY s.visitor_id) as running_total
    FROM sessions s
    JOIN transactions t
    ON s.session_id = t.session_id
    WHERE s.session_ts >= '2020-01-01' AND s.session_ts < '2020-02-01'
  ) sub
Where running_total = 0
AND row_num >= 2

样本表的结果:

欢迎任何反馈,在此先感谢。不确定上述查询是否是正确答案。还想知道我是否也可以像这样显示每个 visitor_id 的单个 session_id:

【问题讨论】:

如果没有事务是要求的一部分,那么内部连接就不能工作。 如果“无事务”意味着 $0 并且仍然记录 session_id,那么内部连接会起作用吗?另外,我的查询是否可以识别“无交易”? 【参考方案1】:

我假设会话是访问。那就是:

select s.visitor_id
from sessions s
where s.session_ts >= '2020-01-01' and s.session_ts < '2020-02-01' and
      not exists (select 1
                  from transactions t
                  where t.session_id = s.session_id
                 )
group by s.visitor_id
having count(*) >= 2;

【讨论】:

很好的建议,效果很好。如果我不得不假设“没有交易”意味着 $0 并且仍然记录了 session_id,我的查询会起作用吗? @KevinKung 。 . .我不明白你的评论是什么意思。您可以调整not exists 逻辑来比较特定类型的交易,例如金额大于零的交易。【参考方案2】:

如果没有负面交易,它会起作用,只是您没有在“运行总数”中添加order by,因此您需要修复它。虽然您在别名中将其称为运行总计,但它根本没有真正运行。不确定这是否是关于命名或实现的混淆。如果您以相反的顺序按美元排序,那么您将走在正确的轨道上,以便首先出现非零行,这样当您到达第二行并且运行总数仍然为零时,那么该访问者确实必须符合条件。但这有点绕道。

为了让访问者独自一人,我只使用简单的group by 来完成这项工作对我来说也更有意义。这本来是我的建议:

GROUP BY s.visitor_id
HAVING COUNT(*) >= 2 AND SUM(revenue) = 0

但由于您想保留会话 ID,毕竟您确实需要分析函数:

SELECT visitor_id, session_id,
    ROW_NUMBER() OVER (PARTITION BY visitor_id ORDER BY session_ts) as row_num
FROM 
(
    SELECT s.visitor_id, s.session_id, s.sessions_ts, 
        SUM(revenue) OVER (PARTITION BY s.visitor_id) as total,
        COUNT(*) OVER (PARTITION BY s.visitor_id) as num_sessions
    FROM sessions s INNER JOIN transactions t
        ON s.session_id = t.session_id
    WHERE s.session_ts >= '2020-01-01' AND s.session_ts < '2020-02-01'
) sub
WHERE total = 0 AND total_sessions >= 2

包含零美元列作为输出没有明确的目的,这就是我将它们排除在外的原因。您甚至可能不需要该行号列,但请注意它现在在外部查询中。

如果可能出现负收入,那么总和并不总是有效。考虑比较这两个值是否相等:

COUNT(*) OVER (PARTITION BY s.visitor_id)

COUNT(CASE WHEN revenue = 0 THEN 1 END) OVER (PARTITION BY s.visitor_id)

【讨论】:

以上是关于如何提取在 2020 年 1 月至少访问过两次但未进行交易的所有 visitor_id 的列表(在他们 1 月的任何一次访问中)的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Mock 应该至少被调用一次但被调用 0 次

在mysql中选择至少有两个[activity]且间隔时间至少为24小时的[sth]

Iphone 模拟器:本地通知触发两次但从不显示?

意外行为 java 优先级队列。对象添加了一次但轮询了两次。怎么可能?

如何在 Flutter 中存储 API 密钥(2020 年 7 月)

访问url地址 但tomcat会发两次请求??