[英]How to pivot this table in SQL
I came across this issue when trying to make use of this "active users" table from Microsoft NAV. 尝试使用Microsoft NAV中的“活动用户”表时遇到了此问题。 What I got asked to do is a Dashboard in Power BI or other tool that will allow the company I work for to understand how many users are active on the NAV system at any point in time. 我被要求做的是Power BI中的仪表板或其他工具,该工具将使我工作的公司可以随时了解有多少用户在NAV系统上处于活动状态。 I found a DAX formula in Power BI that could do the trick - but it requires the following table transformation: 我在Power BI中发现了DAX公式可以解决问题-但它需要进行以下表转换:
I am trying to do this in SQL Management Studio: 我正在尝试在SQL Management Studio中执行此操作:
My SQL Server is Microsoft SQL Azure (RTM) - 12. 我的SQL Server是Microsoft SQL Azure(RTM)-12。
How could I pivot this NAV table below with the following structure knowing that Session ID might repeat further down the line? 我如何使用下面的结构来透视下面的NAV表,从而知道会话ID可能会重复下去?
Session ID | Event Datetime | Event Type
350 2017-07-01 01:00 Logon
350 2017-08-01 02:00 Logoff
351 2017-07-01 02:00 Logon
351 2017-08-01 03:00 Logoff
350 2017-09-01 01:00 Logon
350 2017-09-01 02:00 Logoff
The final result would be each Session ID against their Logon and Logoff time (allowing duplicates if Session ID repeats like in this example) 最终结果将是每个会话ID对应其登录和注销时间(如果像本示例一样重复会话ID,则允许重复)
Thanks a lot in advance. 非常感谢。
Best 最好
Andre 安德烈
This is TSQL code and will run on an Azure database. 这是TSQL代码,将在Azure数据库上运行。 I think this will get you the results you are looking for. 我认为这将为您提供所需的结果。
DECLARE @ActiveUsersLog AS TABLE
(
sessionId INT
,EventDateTime DATETIME
,EventType VARCHAR(50)
);
INSERT INTO @ActiveUsersLog
(
sessionId
,EventDateTime
,EventType
)
VALUES
(350, '2017-07-01 01:00', 'Logon')
,(350, '2017-08-01 02:00', 'Logoff')
,(351, '2017-07-01 02:00', 'Logon')
,(351, '2017-08-01 03:00', 'Logoff')
,(350, '2017-09-01 01:00', 'Logon')
,(350, '2017-09-01 02:00', 'Logoff');
WITH cte_logon
AS (
SELECT aul.sessionId
,aul.EventDateTime
,seq = RANK() OVER (PARTITION BY aul.sessionId ORDER BY aul.EventDateTime)
FROM @ActiveUsersLog AS aul
WHERE aul.EventType = 'Logon'
)
,cte_logoff
AS (
SELECT aul.sessionId
,aul.EventDateTime
,seq = RANK() OVER (PARTITION BY aul.sessionId ORDER BY aul.EventDateTime)
FROM @ActiveUsersLog AS aul
WHERE aul.EventType = 'Logoff'
)
SELECT o.sessionId
,LogonTime = o.EventDateTime
,LogoffTime = f.EventDateTime
FROM cte_logon AS o
LEFT OUTER JOIN cte_logoff AS f
ON o.sessionId = f.sessionId
AND o.seq = f.seq;
If you are only looking for active users then you would add this where clause: (make sure to remove the semicolon at the end of the code above before adding a where clause) 如果您只寻找活动用户,则可以添加以下where子句:(确保在添加where子句之前,在上述代码的末尾删除分号)
where f.EventDateTime is null
Without knowing the flavour of SQL, I can only give you basic advice. 在不了解SQL风格的情况下,我只能提供基本建议。
By performing an inner join with both sides lining to the same table (aliasing appropriately) matching on the session_id
of both sides, you can then filter Event Type
on one of the aliased tables to equal Logon
and Event Type
on the other aliased table to match Logoff
. 通过执行内连接双方衬同一个表(混叠适当地)上的匹配session_id
两侧的,然后可以过滤Event Type
的混叠的表中的一个等于Logon
和Event Type
对其他别名的表,以匹配Logoff
。
This method should work on just about any form of SQL I've used, as it's core functionality of SQL. 由于该方法是SQL的核心功能,因此它几乎可以在我使用的任何形式的SQL上都可以使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.