按一列两行分组

Posted

技术标签:

【中文标题】按一列两行分组【英文标题】:Grouping by one column and two rows 【发布时间】:2012-03-26 18:48:37 【问题描述】:

在下表中,我需要找出登录日期和用户会话的持续时间。例如,empid=1 于 2009 年 1 月 1 日 @ 3:20 登录 (typeid=1) 并在同一天 3:25 注销 (typeid=2)。输出应该是:

logged on,      session length,  sessionid
1/1/2009 3:20   5:00             014A3B2C-3874-4D84-A5B3-F234AA2AE30D

每个 sessionid 都是唯一的。如何创建这样的查询?

create table a (empid int, typeid int, created datetime, sessionid nvarchar(36))

insert into a(empid, typeid, created, sessionid) 
values(1, 1, '01/01/2009 3:20:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30D')
insert into a(empid, typeid, created, sessionid) 
values(1, 2, '01/01/2009 3:25:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30D')
insert into a(empid, typeid, created, sessionid) 
values(2, 1, '01/09/2009 4:20:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30E')
insert into a(empid, typeid, created, sessionid) 
values(3, 1, '01/10/2009 3:25:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30F')
insert into a(empid, typeid, created, sessionid) 
values(2, 2, '01/09/2009 4:23:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30E')
insert into a(empid, typeid, created, sessionid) 
values(3, 2, '01/10/2009 4:25:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30F')
select * from a

drop table a

-- 编辑-- 我想过滤掉一些场景。例如,对于 empid=1,它可能是这样的:

insert into a(empid, typeid, created, sessionid) 
values(1, 1, '01/01/2009 3:20:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30D')
insert into a(empid, typeid, created, sessionid) 
values(1, 1, '01/01/2009 3:25:00', '014A3B2C-3874-4D84-A5B3-F234AA2AE30D')

上述 empid 没有匹配的 typeid=2。有两个 typeid=1。

【问题讨论】:

您必须对会话 ID 进行自我加入。 @DavidFaber - 完全没有必要,一个简单的GROUP BY SessionId 就足够了 【参考方案1】:
select empid,sessionid,
    min(created),max(created),
    datediff(mi,min(created),max(created)) 
from a 
group by empid,sessionid

【讨论】:

谢谢。我为一个场景添加了一个编辑,也许你可以看到如何过滤掉。【参考方案2】:
SELECT LogOn.[created] as [logged on], DATEDIFF(day,LogOn.[created],LogOff.[created]) + ' ' + DATEDIFF(hour,LogOn.[created],LogOff.[created]) + ':' + DATEDIFF(minutes,LogOn.[created],LogOff.[created]) + ':' + DATEDIFF(second,LogOn.[created],LogOff.[created]), a.[sessionid] 
FROM a as [LogOn] 
JOIN a as [LogOff] ON LogOn.[sessionid] = LogOff.[sessionid] 
WHERE LogOn.[typeid] = 1 AND LogOff.[typeid] = 2 

【讨论】:

我建议在 sessionid,typeid 上创建一个唯一的索引/约束。【参考方案3】:
SELECT  SessionId,
        MIN(CASE WHEN typeid = 1 THEN created END) [logged on],
        DATEDIFF(SECOND,MIN(CASE WHEN typeid = 1 THEN created END),MIN(CASE WHEN typeid = 2 THEN created END)) [session length]
FROM a
GROUP BY sessionId

不过,您需要控制会话长度以获得所需的输出格式。

【讨论】:

以上是关于按一列两行分组的主要内容,如果未能解决你的问题,请参考以下文章

MySQL - 按一列分组并获得最低值

使用完全外连接 oracle 按一列分组

sql语句 按一列分组 然后再按别一列组内排序?

如何在此 DataTable 上按一列分组

如何按一列分组并对另一列的值进行排序?

Python:如何按一列分组行并按另一列选择一行?