【leetcode】180.连续出现的数字-中等

【题目】

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

Id Num
1 1
2 1
3 1
4 2
5 1
6 2
7 2

例如,给定上面的Logs表, 1 是唯一连续出现至少三次的数字。

ConsecutiveNums
1

【题解】

法一:内连接

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
;

以上是官方解答,但存在问题:
1.num连续出现,但并不意味着id是连续的;
2.连续出现n次时,n很大sql语句过多需要优化。
于是有了法二。

法二:窗口函数

连续出现的数字是相同的数字,但有可能id是不连续的,所以需要对结果集进行再次编号,让其变为连续的。

# 1.对id进行从1开始的重新排序
select 
  id,num,
  row_number() over (order by id) as nid
from logs

# 2. 对num值进行分组排序
select 
  id,num,
  row_number() over (partition by num order by  id) as numid
from logs

# 3.对步骤1和2中的nid-numid相减,若结果相等则表示数字连续出现,可得最终sql语句
select
  distinct a.num as ConsecutiveNums
from
(
 select 
  id,num,
  (row_number() over (order by id) 
  - row_number() over (partition by num order by id)) as dif
 from logs
) as a
group by a.num,a.dif
having count(*)>=3

法三:分析函数lag()

-- SELECT DISTINCT Num as ConsecutiveNums
-- FROM(
--     SELECT Id,Num,
--     LAG(Num,1)OVER(ORDER BY Id) as last_1,
--     LAG(Num,2)OVER(ORDER BY Id) as last_2
--     FROM Logs
-- ) as consecutivenum
-- WHERE consecutivenum.Num = consecutivenum.last_1
-- AND consecutivenum.last_1 = consecutivenum.last_2

法四:用户变量

利用case when语句判断连续出现的数字

select distinct Num as ConsecutiveNums
from (
  select Num, 
    case 
      when @prev = Num then @count := @count + 1
      when (@prev := Num) is not null then @count := 1
    end as CNT
  from Logs, (select @prev := null,@count := null) as t
) as temp
where temp.CNT >= 3

你可能感兴趣的:(【leetcode】180.连续出现的数字-中等)