sql lead使用

1.场景


假设数据库中存储的日志数据是下面这样的 

timestamp event trace_id node
15320123 request_A 123456 client
15320124 request_B 987654 client
15320125 request_A 123456 access
15320127 request_B 987654 access
15320128 request_B 987654 server
15320129 request_A 123456 server

timestamp就是事件时间戳,即事件发生时程序调用日志上报的时间。event代表事件类型,比如发出了A请求就是request_A。trace_id是一个全链路跟踪id,比如一条消息从客户端,发送到接入服务器,再由接入服务器转发至核心服务器,核心服务器处理完这个消息将回复发送给接入服务器,由接入服务器发送给客户端,这个过程中,所有消息就使用了相同的trace_id来标识。node代表上报这个事件的节点,client代表客户端,access代表接入服务器,server代表核心服务器。

接下来要做一件事,就是统计每一步的耗时,为此我们要把数据处理成下面这样

event fromTime toTime fromNode toNode
request_A 15320123 15320125 client access
request_A 15320125 15320129 access server
request_A 15320129 null server null
request_B 15320124 15320127 client access
request_B 15320127 15320128 access server
request_B 15320128 null server null

怎么做到这一点呢?如果人为的去处理数据,那么我们首先会把数据按照trace_id分组,这一点sql的partition_by可以做到,接下来就是把组里的按时间排序,这一点sql的order_by可以做到,做完这两步,数据会是这样的

timestamp event trace_id node
15320123 request_A 123456 client
15320125 request_A 123456 access
15320129 request_A 123456 server
15320124 request_B 987654 client
15320127 request_B 987654 access
15320128 request_B 987654 server

到了这里,我们发现,剩下要做的事其实就是把相邻的两行捆绑处理一下,前一行是from,后一行是to,然后把前一行的数据和后一行的拼接一下就可以了,那么这个操作用sql怎么实现呢?答案就是,使用lead。

2.lead的使用

首先直接给出最终的sql语句

select
event,
time as fromTime,
lead(timestamp, 1, null) over (
    partition by trace_id
    order by timestamp
) toTime,
node as fromNode,
lead(node, 1, null) over (
    partition by trace_id
    order by timestamp
) toNode
from log.event

这个语句一执行,即可得到最终的效果。

截图为证

(测试环境:在ubuntu1604上装的mysql8,之前装的5.6,不支持这个,ide是datagrip,主要是公司没有买正版的navicat,不过这个用着也不错)

原始数据

sql

执行结果

下面解释一下这一段

lead(timestamp, 1, null) over (
    partition by trace_id
    order by timestamp
) toTime,

lead后面括号里的三个参数分别是(字段名称,行数,默认值),字段名称就是,你要从后面的行里取那个字段;行数就是你要取后面的第几行数据,需要注意的是,这个字段是可以省略的,省略就等同于设为1;默认值就是如果到最后一行了,也就是没有下一行了,这个字段填什么,需要注意的是,这个字段是可以省略的,省略就等同于设为null。所以上面那段代码其实就是,取后面第一行的time字段,如果到最后一行了,这个字段就填null。

over后面的括号里是分组语句和排序语句,当然也可以不填或者任选其一。

最后是给这个字段取个别名。

3.lag

最后提一下lag,虽然我没有用过,不过既然都看了lead,不顺带学一下lag可惜了,因为lag跟lead的用法完全一样,只不过lead是取后面某行的数据,而lag是前面。

发布了17 篇原创文章 · 获赞 22 · 访问量 3030

猜你喜欢

转载自blog.csdn.net/u013536232/article/details/103545895