间隙和孤岛问题-对数据的连续运行进行分组以获取最大和最小日期

问题描述

我有一个使用Oracle无法解决的空白问题。

我试图在连续的LOGIN_TIMEPC_ID序列中获得具有相同值的第一个和最后一个事件(USER_NAME)。在此示例中,我想要MIN(LOGIN_TIME)MAX(LOGIN_TIME),但只希望在'jane'登录之前的前三个登录中使用。然后,我希望对'jane'使用相同的登录方式,依此类推。>

查询

SELECT 
    PC_ID,USER_NAME,LOGIN_TIME
FROM
    LOGIN_AUDIT
WHERE PC_ID = 72
AND LOGIN_TIME BETWEEN '2020-08-10 00:00:00' AND '2020-08-18 00:00:00'
;

上述查询的输出如下:

| PC_ID | USER_NAME | LOGIN_TIME          |
|-------|-----------|---------------------|
| 72    | bob       | 2020-08-10 09:00:00 |
| 72    | bob       | 2020-08-10 13:30:00 |
| 72    | bob       | 2020-08-11 09:00:00 |
| 72    | jane      | 2020-08-12 08:00:00 |
| 72    | jane      | 2020-08-13 09:00:00 |
| 72    | jane      | 2020-08-13 14:30:00 |
| 72    | bob       | 2020-08-14 08:00:00 |
| 72    | bob       | 2020-08-15 08:00:00 |
| 72    | bob       | 2020-08-16 08:00:00 |
| 72    | bob       | 2020-08-17 08:00:00 |

我正在寻找的输出是这样:

| PC_ID | USER_NAME | FIRST_LOGIN         | LAST_LOGIN          |
|-------|-----------|---------------------|---------------------|
| 72    | bob       | 2020-08-10 09:00:00 | 2020-08-11 09:00:00 |
| 72    | jane      | 2020-08-12 08:00:00 | 2020-08-13 14:30:00 |
| 72    | bob       | 2020-08-14 08:00:00 | 2020-08-17 08:00:00 |

我们将不胜感激。

解决方法

解决这类间隙和孤岛问题的一种简单方法是行数差异法。考虑:

WITH cte AS (
    SELECT t.*,ROW_NUMBER() OVER (PARTITION BY PC_ID ORDER BY LOGIN_TIME) rn1,ROW_NUMBER() OVER (PARTITION BY PC_ID,USER_NAME ORDER BY LOGIN_TIME) rn2
    FROM yourTable t
)

SELECT
    PC_ID,USER_NAME,MIN(LOGIN_TIME) AS FIRST_LOGIN,MAX(LOGIN_TIME) AS LAST_LOGIN
FROM cte
GROUP BY
    PC_ID,(rn1 - rn2)
ORDER BY
    MIN(LOGIN_TIME);

screen capture from demo link below

Demo

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...