将行中相应的开始-停止时间转换为列
Posted
技术标签:
【中文标题】将行中相应的开始-停止时间转换为列【英文标题】:Transforming corresponding Start-Stop Time in rows to columns 【发布时间】:2021-12-30 12:39:55 【问题描述】:我有一个这种格式的表格:
User | Time | status |
---|---|---|
User 1 | 2021-12-24 14:00:00 | connect |
User 2 | 2021-12-24 14:05:23 | connect |
User 2 | 2021-12-24 14:10:11 | disconnect |
User 2 | 2021-12-24 14:10:17 | connect |
User 1 | 2021-12-24 19:35:22 | disconnect |
User 2 | 2021-12-25 01:10:40 | disconnect |
我想要一个表格,其中包含连接和断开连接作为列,每个会话从连接到每个用户的下一个断开连接都有一行
User | connect | disconnect |
---|---|---|
User 1 | 2021-12-24 14:00:00 | 2021-12-24 19:35:22 |
User 2 | 2021-12-24 14:05:23 | 2021-12-24 14:10:11 |
User 2 | 2021-12-24 14:10:17 | 2021-12-25 01:10:40 |
我可以在 mysql、MariaDB 或 MSSQL 上创建它,具体取决于在哪里更容易。可以作为视图吗?很棒的插件,但并非绝对必要:“持续时间”列显示每个会话从连接到断开连接的持续时间。
如果更简单,连接/断开连接时间可能是从 1970/1/1 开始的 (mili) 秒。
【问题讨论】:
【参考方案1】:尝试以下解决方案,它应该适用于大多数 RDBMS,注意正确分隔与保留字冲突的列名。
首先,您需要配对连接/断开连接,这可以通过对行编号,然后使用模数复制每隔一个数字,然后使用条件聚合来完成:
with rn as (
select *,
Row_Number() over(partition by user order by time) rn
from t
), gp as (
select *,
case when rn %2=0 then
Lag(rn) over(partition by user order by rn)
else rn end gp
from rn
)
select
[user],
Max(case when status = 'connect' then time end) Connect,
Max(case when status = 'disconnect' then time end) Disconnect
from gp
group by user, gp
【讨论】:
【参考方案2】:条件聚合可以在应用ROW_NUMBER()
窗口函数后使用,如果你的可用数据库版本是8.0+, MySQL、MariaDB 和 SQL Server 分别为 10.2+ 和 2005,例如
WITH t2 AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY user,status ORDER BY time) AS rn,
t.*
FROM t
)
SELECT User,
MAX(CASE WHEN status = 'connect' THEN time END) AS connect,
MAX(CASE WHEN status = 'disconnect' THEN time END) AS disconnect
FROM t2
GROUP BY user, rn
ORDER BY user, rn
在哪里
数据集按 user
和 status
列分组,而
按time
列
user
,这是一个保留关键字,必须替换为 [user]
作为 SQL Server 的列名 数据库
Demo for MySQL/MariaDB
Demo for SQL Server
【讨论】:
以上是关于将行中相应的开始-停止时间转换为列的主要内容,如果未能解决你的问题,请参考以下文章