处理SQL中的顺序/有序数据

时间:2016-02-04 17:00:50

标签: mysql sql

我很抱歉,如果已经提出这个问题,尝试搜索但找不到相关的帖子。

我获得了一个半大数据源(约15万条记录),我需要对其进行一些分析以确定用户行为。数据源包括用户ID的字段,事务的日期以及指示事务是否具有特定特征的标志。显然,我在这里简化了问题的核心。用户的交易数量会有很大差异(从1到200+),日期分布会有所不同,标志的分布会有所不同。

考虑下表:

ID          User ID         Date             Flag
1           1               2015-01-03       Y
2           1               2015-03-15       N
3           1               2015-07-20       N
4           1               2015-11-18       N
5           1               2015-11-29       N
6           2               2015-02-16       Y
7           2               2015-03-03       N
8           2               2015-06-10       Y
9           2               2015-08-10       Y

如何根据同一用户之前或之后的其他记录的特征查询此数据以隔离记录?

例如:

  1. 如何识别带有' Y'标志后面跟着另外三个记录(按日期排序),用于相同的用户ID,其中包含' N'旗? [将在上表中返回1]

  2. 如何识别用户ID,其中50%或更多的交易使用' Y'旗帜出现在前20%的交易中? [将返回上表中的用户ID]

  3. 我希望这个问题很清楚。

    *编辑:以下答案是正确的,但是他不知道我使用MySQL作为数据库(我在回答后添加了标签)。 MySQL不支持这些功能,Oracle或SQL Server都可以实现这些功能。

1 个答案:

答案 0 :(得分:3)

这个问题假设一个合理的数据库支持窗口/分析函数。

可以使用lead()处理第一个问题:

select t.*
from (select t.*,
             lead(flag, 1) over (partition by userid order by date) as flag_1,
             lead(flag, 2) over (partition by userid order by date) as flag_2,
             lead(flag, 3) over (partition by userid order by date) as flag_3
      from t
     ) t
where flag = 'Y' and flag_1 = 'N' and flag_2 = 'N' and flag_3 = 'N';

第二个也使用窗口函数:

select user_id
from (select t.*,
             row_number() over (partition by user_id order by date) as seqnum,
             count(*) over (partition by user_id) as cnt
      from t
     ) t
group by user_id
having sum(case when flag = 'Y' and seqnum/0.2 <= cnt then 1 else 0 end) >=
           0.5 * sum(case when flag = 'Y' then 1 else 0 end);

因此,您的问题的答案基本上是:了解窗口(分析)函数。