1

我有两个表:让我们称它们为 INSTALLS 和 EXECUTES。

INSTALLS 表的结构为:user_id BIGINT、install_ts BIGINT。

EXECUTES 表具有相同的结构:user_id BIGINT、exec_ts BIGINT。

user_id 很明显,_ts 字段是时间戳,表示为从 Unix 纪元开始计算的秒数。

这两个表填充如下:

每次用户安装我的应用程序时,都会填充 INSTALLS 表。然后他可以卸载并重新安装,在这种情况下,同一用户的另一行出现在此表中(但不同的 ts)。对于我所有的分析,我需要使用最旧的安装时间戳。

每次用户使用我的应用程序时,都会填充 EXECUTES 表 - 使用 user_id 和执行时间。

我需要用这种结构创建一个汇总表:

日期、该日期的安装次数、后续日期的使用次数

这就是我解决问题的方式:

  1. 获取最早的安装日期:

    SELECT user_id, DATE(MIN(install_ts)) AS install_date FROM INSTALLS GROUP BY user_id

  2. 获取执行日期(需要满足给定日期的多次执行):

    SELECT user_id, DATE(exec_ts) AS exec_date FROM EXECUTES GROUP BY user_id, DATE(exec_ts)

  3. 结合这两个:

    SELECT a.install_date, COUNT(a.user_id) AS install_count, COUNT(b.user_id) AS usage_count FROM (SELECT user_id, DATE(MIN(install_ts)) AS install_date FROM INSTALLS GROUP BY user_id) a LEFT OUTER JOIN (SELECT user_id, DATE(exec_ts) AS exec_date FROM EXECUTES GROUP BY user_id, DATE(exec_ts)) b ON a.user_id = b.user_id GROUP BY a.install_date

这将计算任何时候使用我的应用程序的所有用户。从这个数据集中,我现在只需要提取那些在安装日期的紧随其后的日期使用我的应用程序的用户。

我考虑的一种方法是增加一个 JOIN 条件。当我这样做时,我得到(首先查询,下面的错误):

SELECT a.install_date, COUNT(a.user_id) AS install_count, COUNT(b.user_id) AS usage_count
FROM
    (SELECT user_id, DATE(MIN(install_ts)) AS install_date FROM INSTALLS GROUP BY user_id) a
    LEFT OUTER JOIN
    (SELECT user_id, DATE(exec_ts) AS exec_date FROM EXECUTES GROUP BY user_id, DATE(exec_ts)) b
    ON a.user_id = b.user_id AND DATEDIFF(b.exec_date, a.install_date) = 1
GROUP BY a.install_date

在 JOIN '1' 中遇到左右别名

我考虑的第二种方法是在 WHERE 子句中使用 DATEDIFF:

SELECT a.install_date, COUNT(a.user_id) AS install_count, COUNT(b.user_id) AS usage_count
FROM
    (SELECT user_id, DATE(MIN(install_ts)) AS install_date FROM INSTALLS GROUP BY user_id) a
    LEFT OUTER JOIN
    (SELECT user_id, DATE(exec_ts) AS exec_date FROM EXECUTES GROUP BY user_id, DATE(exec_ts)) b
    ON a.user_id = b.user_id
WHERE b.user_id IS NULL OR DATEDIFF(b.exec_date, a.install_date) = 1
GROUP BY a.install_date

但我可以看出这是完全错误的——如果用户在第 1 天安装并在第 3 天返回,他将不会被计入 install_count(因为他不会出现在连接表中)。所以现在我有点没有想法了。我对 SQL 有点陌生,因此非常感谢任何帮助。

4

2 回答 2

2

如果我完全理解,结果行将包含日期、唯一用户在该日期的安装次数,以及在所有用户安装后的第二天执行程序的次数......所以,那里每个日期有 2 次不同的计算。

我的解决方案从两个表的连接开始(没有您使用的分组),然后后续操作使用分析功能,然后进行分组。在我的测试中,表格使用字符串类型,所以日期看起来像“2013-08-01”等,可以使用 DATEDIFF。

我创建了一个中间连接结果表,但这可以很容易地汇总到最终查询中。此联接表将包含每个用户的一行,其中包含安装日期和 1 或 0,以指示第二天是否有执行。

create table i_e_join as
select i.user_id, i.install_ts,
       if (e.exec_ts is null OR (DATEDIFF(e.exec_ts,i.install_ts) > 1), 0,1)
         over (partition by i.user_id,i.install_ts) as has_exec
from tmp_installs i left outer join tmp_executes e on (i.user_id = e.user_id);

然后一个简单的 group by 来获得每个 install_ts 的结果:

select install_ts, count(distinct user_id) as install_count, 
       sum(has_exec) as usage_count from i_e_join
group by install_ts;

创建连接表的关键是使用分析函数来计算 has_exec 字段,该字段在 install_ts 上查看来自用户的所有行。

于 2013-09-26T16:59:01.420 回答
1

我自己解决了这个问题。我是这样做的:

SELECT x.install_date, COUNT(x.user_id) AS install_count, COUNT(y.user_id) AS usage_count
FROM (
    SELECT user_id, DATE(MIN(install_ts)) AS install_date FROM INSTALLS GROUP BY user_id
) x LEFT OUTER JOIN (
    SELECT a.user_id AS user_id, a.install_date AS install_date, b.exec_date AS exec_date
    FROM
        (SELECT user_id, DATE(MIN(install_ts)) AS install_date FROM INSTALLS GROUP BY user_id) a
        JOIN
        (SELECT user_id, DATE(exec_ts) AS exec_date FROM EXECUTES GROUP BY user_id, DATE(exec_ts)) b
        ON a.user_id = b.user_id
        WHERE DATEDIFF(b.exec_date, a.install_date) = 1
) y
GROUP BY x.install_date
于 2013-10-01T07:01:08.113 回答