Description

Table: Stadium

Column NameType
idint
visit_datedate
peopleint
  • visit_date is the column with unique values for this table.
  • Each row of this table contains the visit date and visit id to the stadium with the number of people during the visit.
  • As the id increases, the date increases as well.

Problem Statement

Write a solution to display the records with three or more rows with consecutive id’s, and the number of people is greater than or equal to 100 for each. Return the result table ordered by visit_date in ascending order.

The result format is in the following example.

Example 1:

Input:

  • Stadium table
idvisit_datepeople
12017-01-0110
22017-01-02109
32017-01-03150
42017-01-0499
52017-01-05145
62017-01-061455
72017-01-07199
82017-01-09188

Output:

idvisit_datepeople
52017-01-05145
62017-01-061455
72017-01-07199
82017-01-09188

Explanation:

  • The four rows with ids 5, 6, 7, and 8 have consecutive ids and each of them has >= 100 people attended. Note that row 8 was included even though the visit_date was not the next day after row 7.
  • The rows with ids 2 and 3 are not included because we need at least three consecutive ids.

Solution

The problem can be divided into following parts:

  1. First of all, you need to find only those rows for which people >= 100. So, you need to filter the rows where people >= 100.
1SELECT * 
2    FROM Stadium
3    WHERE people >= 100;
  1. You need to output rows which have consecutive ids. The three subsequent ids can be either the current and two previous, current, previous and next or current and next two. Now, in order to get previous two values, you can get them using LAG(id, 1) and LAG(id, 2). In order to get next two ids, you can use LEAD(id, 1) and LEAD(id, 2).
1SELECT id, visit_date, people,
2    LAG(id, 1) OVER (ORDER BY id) AS previous_id,
3    LAG(id, 2) OVER (ORDER BY id) AS second_previous_id,
4    LEAD(id, 1) OVER (ORDER BY id) AS next_id,
5    LEAD(id, 2) OVER (ORDER BY id) AS second_next_id
6    FROM Stadium
7    WHERE people >= 100;
  1. Once you’ve got consecutive ids, you have to output rows where the difference between ids is 1. This will ensure that the ids are consecutive ids. You can use WHERE clause for this.
1WHERE (
2    (id - previous_id = 1 AND previous_id - second_previous_id = 1) OR
3    (id - previous_id = 1 AND next_id - id = 1) OR
4    (second_next_id - next_id = 1 AND next_id - id = 1)
5) ORDER BY visit_date;

The final solution looks like below.

 1WITH tmp AS (
 2    SELECT id, visit_date, people,
 3        LAG(id, 1) OVER (ORDER BY id) AS previous_id,
 4        LAG(id, 2) OVER (ORDER BY id) AS second_previous_id,
 5        LEAD(id, 1) OVER (ORDER BY id) AS next_id,
 6        LEAD(id, 2) OVER (ORDER BY id) AS second_next_id
 7        FROM Stadium
 8        WHERE people >= 100
 9) SELECT id, visit_date, people
10    FROM tmp
11    WHERE (
12        (id - previous_id = 1 AND previous_id - second_previous_id = 1) OR
13        (id - previous_id = 1 AND next_id - id = 1) OR
14        (second_next_id - next_id = 1 AND next_id - id = 1)
15    ) ORDER BY visit_date;