如何在SQL

时间:2017-11-23 18:12:32

标签: sql pivot

我在尝试使用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重复,则允许重复,如本示例所示)

提前多多感谢。

最佳

安德烈

2 个答案:

答案 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}}和LogonEvent Type匹配。

这种方法应该适用于任何形式的SQL,因为它是SQL的核心功能。