将行中相应的开始-停止时间转换为列

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+ MySQLMariaDBSQL 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

在哪里

数据集按 userstatus 列分组,而 按time

排序

user,这是一个保留关键字,必须替换为 [user] 作为 SQL Server 的列名 数据库

Demo for MySQL/MariaDB

Demo for SQL Server

【讨论】:

以上是关于将行中相应的开始-停止时间转换为列的主要内容,如果未能解决你的问题,请参考以下文章

将行值转换为列,其值来自 spark scala 中的另一列 [重复]

如何使用 Postgresql 将行转换为列?

将行转换为列

将行数据转换为列

pyspark 将行转换为列

不能从子查询将行转换为列