差距和岛屿问题 - 对数据的顺序运行进行分组以获得最大和最小日期

Gaps and islands question - Grouping sequential runs of data to get max and min dates

我有一个使用 Oracle 无法解决的间隙和孤岛问题。

我试图让 PC_IDUSER_NAME 的连续系列中的第一个和最后一个事件 (LOGIN_TIME) 具有相同的值。在这个例子中,我想要 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,
    USER_NAME,
    (rn1 - rn2)
ORDER BY
    MIN(LOGIN_TIME);

Demo