需要按月计算唯一交易,但忽略该 ID 第一次输入后 3 天发生的记录
Need to count unique transactions by month but ignore records that occur 3 days after 1st entry for that ID
我有一个只有两列的 table:User_ID 和 fail_date。每次有人的卡被拒绝时,他们都会登录 table,他们的卡会在 3 天后自动重试,如果他们再次失败,则会将另一个条目添加到 table。我正在尝试编写一个按月计算唯一失败次数的查询,因此我只想计算第一个条目,而不是 3 天重试次数(如果存在)。我的数据集看起来像这样
user_id fail_date
222 01/01
222 01/04
555 02/15
777 03/31
777 04/02
222 10/11
所以我想要的输出是这样的:
month unique_fails
jan 1
feb 1
march 1
april 0
oct 1
我会在 Vertica 中 运行 这个,但我并不是在寻找回复中的完美语法。只是帮助解决这个问题,因为我真的想不出一种方法来让它发挥作用。谢谢!
您可以使用 lag()
获取每个用户之前的时间戳。如果当前时间戳和之前的时间戳相隔小于或恰好三天,则为跟进。将行标记为这样。然后您可以过滤以排除跟进。
它可能看起来像:
SELECT month,
count(*) unique_fails
FROM (SELECT month(fail_date) month,
CASE
WHEN datediff(day,
lag(fail_date) OVER (PARTITION BY user_id,
ORDER BY fail_date),
fail_date) <= 3 THEN
1
ELSE
0
END follow_up
FROM elbat) x
WHERE follow_up = 0
GROUP BY month;
我不太确定 Vertica 中的确切语法,因此它可能需要一些调整。我也不知道,如果 fail_date
实际上是某种 date/time 类型的变体或只是一个字符串。如果它只是一个字符串,date/time 特定函数可能无法处理它并且必须被替换,或者在将它传递给函数之前必须转换字符串。
如果数据跨越数年,您可能还希望在月份之外还包括年份,以将不同年份的月份分开。在内部 SELECT
添加一列 year(fail_date) year
并将 year
添加到列列表和外部 SELECT
.
的 GROUP BY
您可以通过以下操作添加关于这是否是 "unique_fail" 的标志:
select t.*,
(case when lag(fail_date) over (partition by user_id order by fail_date) > fail_date - 3
then 0 else 1
end) as first_failure_flag
from t;
那么,你想按月统计这个标志:
select to_char(fail_date, 'Mon'), -- should aways include the year
sum(first_failure_flag)
from (select t.*,
(case when lag(fail_date) over (partition by user_id order by fail_date) > fail_date - 3
then 0 else 1
end) as first_failure_flag
from t
) t
group by to_char(fail_date, 'Mon')
order by min(fail_date)
- 在Derived Table, determine the previous fail_date (
prev_fail_date
), for a specific user_id
and fail_date
, using a Correlated subquery.
- 使用导出的table
dt
, Count 失败,如果当前fail_date
和prev_fail_date
之间的天数差为大于 3.
- DateDiff() function alongside with If()函数用于判断情况,哪些不重复试。
- 月
Group By
这个结果,可以使用MONTH函数。
- 但是,数据可以来自多年,所以你需要将它们分开yearwise,这样你就可以也可以使用 YEAR 函数进行多级分组。
尝试以下(在 MySQL 中)- 您也可以了解其他 RDBMS:
SELECT YEAR(dt.fail_date) AS year_fail_date,
MONTH(dt.fail_date) AS month_fail_date,
COUNT( IF(DATEDIFF(dt.fail_date, dt.prev_fail_date) > 3, user_id, NULL) ) AS unique_fails
FROM (
SELECT
t1.user_id,
t1.fail_date,
(
SELECT t2.fail_date
FROM your_table AS t2
WHERE t2.user_id = t1.user_id
AND t2.fail_date < t1.fail_date
ORDER BY t2.fail_date DESC
LIMIT 1
) AS prev_fail_date
FROM your_table AS t1
) AS dt
GROUP BY
year_fail_date,
month_fail_date
ORDER BY
year_fail_date ASC,
month_fail_date ASC
我有一个只有两列的 table:User_ID 和 fail_date。每次有人的卡被拒绝时,他们都会登录 table,他们的卡会在 3 天后自动重试,如果他们再次失败,则会将另一个条目添加到 table。我正在尝试编写一个按月计算唯一失败次数的查询,因此我只想计算第一个条目,而不是 3 天重试次数(如果存在)。我的数据集看起来像这样
user_id fail_date
222 01/01
222 01/04
555 02/15
777 03/31
777 04/02
222 10/11
所以我想要的输出是这样的:
month unique_fails
jan 1
feb 1
march 1
april 0
oct 1
我会在 Vertica 中 运行 这个,但我并不是在寻找回复中的完美语法。只是帮助解决这个问题,因为我真的想不出一种方法来让它发挥作用。谢谢!
您可以使用 lag()
获取每个用户之前的时间戳。如果当前时间戳和之前的时间戳相隔小于或恰好三天,则为跟进。将行标记为这样。然后您可以过滤以排除跟进。
它可能看起来像:
SELECT month,
count(*) unique_fails
FROM (SELECT month(fail_date) month,
CASE
WHEN datediff(day,
lag(fail_date) OVER (PARTITION BY user_id,
ORDER BY fail_date),
fail_date) <= 3 THEN
1
ELSE
0
END follow_up
FROM elbat) x
WHERE follow_up = 0
GROUP BY month;
我不太确定 Vertica 中的确切语法,因此它可能需要一些调整。我也不知道,如果 fail_date
实际上是某种 date/time 类型的变体或只是一个字符串。如果它只是一个字符串,date/time 特定函数可能无法处理它并且必须被替换,或者在将它传递给函数之前必须转换字符串。
如果数据跨越数年,您可能还希望在月份之外还包括年份,以将不同年份的月份分开。在内部 SELECT
添加一列 year(fail_date) year
并将 year
添加到列列表和外部 SELECT
.
GROUP BY
您可以通过以下操作添加关于这是否是 "unique_fail" 的标志:
select t.*,
(case when lag(fail_date) over (partition by user_id order by fail_date) > fail_date - 3
then 0 else 1
end) as first_failure_flag
from t;
那么,你想按月统计这个标志:
select to_char(fail_date, 'Mon'), -- should aways include the year
sum(first_failure_flag)
from (select t.*,
(case when lag(fail_date) over (partition by user_id order by fail_date) > fail_date - 3
then 0 else 1
end) as first_failure_flag
from t
) t
group by to_char(fail_date, 'Mon')
order by min(fail_date)
- 在Derived Table, determine the previous fail_date (
prev_fail_date
), for a specificuser_id
andfail_date
, using a Correlated subquery. - 使用导出的table
dt
, Count 失败,如果当前fail_date
和prev_fail_date
之间的天数差为大于 3. - DateDiff() function alongside with If()函数用于判断情况,哪些不重复试。
- 月
Group By
这个结果,可以使用MONTH函数。 - 但是,数据可以来自多年,所以你需要将它们分开yearwise,这样你就可以也可以使用 YEAR 函数进行多级分组。
尝试以下(在 MySQL 中)- 您也可以了解其他 RDBMS:
SELECT YEAR(dt.fail_date) AS year_fail_date,
MONTH(dt.fail_date) AS month_fail_date,
COUNT( IF(DATEDIFF(dt.fail_date, dt.prev_fail_date) > 3, user_id, NULL) ) AS unique_fails
FROM (
SELECT
t1.user_id,
t1.fail_date,
(
SELECT t2.fail_date
FROM your_table AS t2
WHERE t2.user_id = t1.user_id
AND t2.fail_date < t1.fail_date
ORDER BY t2.fail_date DESC
LIMIT 1
) AS prev_fail_date
FROM your_table AS t1
) AS dt
GROUP BY
year_fail_date,
month_fail_date
ORDER BY
year_fail_date ASC,
month_fail_date ASC