假设我在表格中存储与events
相关联的users
,如下所示(dt
代表事件的时间戳):
| dt | user | event |
| 1 | 1 | A |
| 2 | 1 | D |
| 3 | 1 | B |
| 4 | 1 | C |
| 5 | 1 | B |
| 6 | 2 | B |
| 7 | 2 | B |
| 8 | 2 | A |
| 9 | 2 | A |
| 10 | 2 | C |
这样我们可以说:
我想要回答的有关这些用户的问题类型很容易表达为对事件序列的常规表达,例如: “哪些用户有事件序列匹配A. * B?”或“哪些用户的事件序列匹配A [^ C] * B [^ C] * D?”等
我可以使用什么样的好的SQL技术或运算符来回答这个表结构上的类似查询?
有没有办法有效/动态生成user
- 到 - event-sequence
的表格,然后可以使用正则表达式进行查询?
我目前正在使用Postgres,但我很想知道是否有任何像SQLServer或Oracle这样的大型DBMS也有专门的运营商。
答案 0 :(得分:5)
使用Postgres 9.x这实际上非常简单:
select userid,
string_agg(event, '' order by dt) as event_sequence
from events
group by userid;
使用该结果,您现在可以在event_sequence上应用正则表达式:
select *
from (
select userid,
string_agg(event, '' order by dt) as event_sequence
from events
group by userid
) t
where event_sequence ~ 'A.*B'
使用Postgres 8.x你需要找到string_agg()函数的替代品(只是google for it,那里有很多例子)你需要一个子选择来确保聚合的排序为8.x确实支持聚合函数中的order by
。
答案 1 :(得分:1)
我不是在计算机上为这个答案编写代码,但这里是我如何在SQL Server中使用基于RegEx的解决方案:
这应该最终为您提供原始问题请求的SQL Server功能,但是,如果您正在分析一个非常大的数据集,这可能会非常慢,并且可能有更好的方法来完成您正在寻找的内容对
答案 2 :(得分:1)
对于 Oracle (版本11g R2):
如果您使用的是Oracle DB 11g R2,请查看listagg。下面的代码应该可以工作,但我还没有测试过。重点是:您可以使用listagg
。
SQL> select user,
2 listagg( event, '' )
3 within group (order by dt) events
4 from users
5 group by user
6 order by dt
7 /
USER EVENTS
--------- --------------------
1 ADBCB
2 BBAAC
在以前的版本中,您可以使用CONNECT BY子句。有关listagg的更多详情。