【力扣 】查找所有至少连续出现三次的数字/求连续登录3天的用户数(SQL完成)

0. 题目

编写一个 SQL 查询,查找所有至少连续出现三次的数字。

返回的结果表中的数据可以按 任意顺序 排列。

输入:
Logs 表:
±—±----+
| Id | Num |
±—±----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
±—±----+
输出:
Result 表:
±----------------+
| ConsecutiveNums |
±----------------+
| 1 |
±----------------+
解释:1 是唯一连续出现至少三次的数字。

1. 关键

核心思想是要想明白这个结论: 如果一个num连续出现时,那么它出现的[真实序列]-它出现的次数一定是个定值。 因为:

  • 假设一个num出现后,它的 真实序列 为 i ,同时假设它是第 k 次出现的; 差值为i-k.
  • 当它连续出现一次时,它的 真实序列 一定为 i+1 ; 它的出现次数显然也会+1,为 k+1 ; 差值为 i+1-(k+1)=i-k.
  • 当它连续出现第 n 次时,它的 真实序列 一定为 i+n;它出现的次数为 k+n;差值为 i+n-(k+n)=i-k.
  • 如果它不连续出现,假设m个其他num出现之后,它又出现了,它的真实序列为i+n+m+1,差值为i-k+m”,所以当m不为0时,差值不为i-k。

官解是直接三表联查

SELECT DISTINCT
l1.Num AS ConsecutiveNums
FROM
Logs l1,
Logs l2,
Logs l3
WHERE
l1.Id = l2.Id - 1
AND l2.Id = l3.Id - 1
AND l1.Num = l2.Num
AND l2.Num = l3.Num
;

官解如果id不连续,根据Id计算会出现bug

2. 窗口函数

连续的关键: 真实序列-分区后出现的次数=定值

SELECT DISTINCT Num FROM (
SELECT Num,COUNT(1) as SerialCount FROM
(SELECT Id,Num,
ROW_NUMBER() over(order by id) -
ROW_NUMBER() over(partition by Num order by Id) as SerialNumberSubGroup
FROM ContinueNumber) as Sub
GROUP BY Num,SerialNumberSubGroup HAVING COUNT(1) >= 3) as Result

https://leetcode.cn/problems/consecutive-numbers/solutions/21537/sql-server-jie-fa-by-neilsons/

3.求连续登录3天的用户数

SELECT user_id
FROM (
SELECT
user_id,
login_date,
row_number() OVER(PARTITION BY user_id ORDER BY login_date) AS rn,
date_sub(login_date, rn) AS flag_date
FROM t_user
) tmp
GROUP BY tmp.user_id, date_sub(login_date, rn) – 每个用户每次连续登录的分块
HAVING COUNT(1) >= 3

注:上述代码仅求出了连续登录3天以上的所有user_id,并非user_id数。

https://www.nowcoder.com/discuss/353148341368332288?sourceSSR=search

你可能感兴趣的:(sql,leetcode,数据库)