365 Days of Daily Coding: Day 10

Today’s leetcode challenge was very challenging. It’s frustrating to not be able to answer at the same time not easily be able to understand other sucessful submissions.

Given a table, I had to find out the numbers that were repeated three times consecutively.

IdNum
11
21
31
42
51
62
72
Sample of the table ‘Logs’

Expected Output:

ConsecutiveNums
1
Sample of the expected output

Solution 1:

 SELECT DISTINCT Num AS ConsecutiveNums
 FROM (
     SELECT Id, Num
         , lead(ID, 2) OVER (PARTITION BY Num ORDER BY id) AS id2
     FROM Logs
 ) a
 WHERE a.id2 = a.id + 2 

To understand this solution, we would need to understand the ‘LEAD()’ function. The LEAD function is an analytic function that lets you query more than one rows and return value from the next nth rows of the table.

Syntax:

 LEAD ( expression [, offset [, default] ] )
 OVER ( [ query_partition_clause ] order_by_clause ) 

Breaking down the query:

I used the Live SQL freely available from Oracle to test out the subqueries. First I built a temporary table with the ‘WITH’ function as follows.

WITH
   Logs as (
     select 1 as Id, 1 as Num    from dual union all
     select 2      , 1           from dual union all
     select 3      , 1           from dual union all
     select 4      , 2           from dual union all
     select 5      , 1           from dual union all
     select 6      , 2           from dual union all
     select 7      , 2           from dual 
 ) 

Query 1:

 SELECT Id, Num, LEAD(ID, 2) OVER (PARTITION BY Num ORDER BY Id) AS id2
     FROM Logs; 

Output:

IDNumID2
113
215
31
51
427
62
72
Sample of the output of Query 1

The query first partitions the table by ‘Num’ meaning that the table is grouped by the same values in Num. The partitions is then ordered by ID no. in ascending order. After which the ‘LEAD(ID, 2)’ function returns the ID no of the row after offsetting 2 rows.

Query 2:

 SELECT DISTINCT Num AS ConsecutiveNums
 FROM (
     SELECT Id, Num
         , lead(ID, 2) OVER (PARTITION BY Num ORDER BY id) AS id2
     FROM Logs
 ) a
 WHERE a.id2 = a.id + 2 

The outer ‘SELECT’ and ‘WHERE’ function then returns only those rows if the ID no. + 2 matches the ID2.

Solution 2:

SELECT DISTINCT Num AS "ConsecutiveNums" FROM
(
SELECT Num, LAG(Num) OVER (ORDER BY Id) AS prev,
LEAD(Num) OVER (ORDER BY Id) AS next FROM Logs
)
WHERE Num=prev AND Num=next;

Just like the ‘LEAD()’, ‘LAG()’ is another analytic function that queries more than one row in a table but retuns the previous nth rows in a table.

The output of the query selecting all the columns would look as below.

IdNumprevnext
111
2111
3112
4211
5122
6212
722
Sample of the solution 2 when all columns are selected

With the ‘WHERE Num=prev AND Num=next’ syntax, only 1 row fulfils the condition which is the second row as the Num ‘1’ has 1 in the prev row and 1 in the next row.

Leave a comment