我在尝试使用Microsoft NAV中的“活跃用户”表时遇到了这个问题。我要求做的是Power BI中的仪表板或其他工具,这将允许我工作的公司了解在任何时间点有多少用户在NAV系统上处于活动状态。我在Power BI中找到了一个可以解决这个问题的DAX公式 - 但它需要进行以下表格转换:
我正在尝试在SQL Management Studio中执行此操作:
我的SQL Server是Microsoft SQL Azure(RTM) - 12。
我如何使用以下结构将此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
最终结果是每个会话ID与其登录和注销时间相对应(如果会话ID重复,则允许重复,如本示例所示)
提前多多感谢。
最佳
安德烈
答案 0 :(得分:1)
这是TSQL代码,将在Azure数据库上运行。我想这会得到你想要的结果。
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;
如果您只是在寻找活跃用户,那么您可以在where子句中添加:(确保在添加where子句之前删除上面代码末尾的分号)
where f.EventDateTime is null
答案 1 :(得分:0)
在不知道SQL风格的情况下,我只能给你基本的建议。
通过执行内部连接,两边都在同一个表(适当别名)上匹配,并匹配两边的session_id
,然后可以在其中一个别名表上过滤Event Type
以等于{另一个别名表上的{1}}和Logon
与Event Type
匹配。
这种方法应该适用于任何形式的SQL,因为它是SQL的核心功能。