1.sql title description
Say there is a log table with only two columns, which are consecutive id and num. As for what it means, treat it as an amount. Now I want to know the num of 3 consecutive times or more. The data is as follows
id | on one |
---|---|
1 | 1 |
2 | 1 |
3 | 1 |
4 | 2 |
5 | 3 |
6 | 4 |
7 | 4 |
8 | 4 |
Then the result is only 1, 4 meet the conditions, ask how to write this SQL?
2. Ideas and solutions
Analysis: The title is simple, there is no ambiguity, and can be understood. For problems like several consecutive times, the window function must be used. The first thing that comes to mind is the ranking row_number
and lag
how to reflect the continuity. It must be a sorted id. The title gives the id is continuously increasing, row_number can be omitted
So the first step, go to lag, the result is as follows:
id | on one | lagid |
---|---|---|
1 | 1 | null |
2 | 1 | 0 |
3 | 1 | 0 |
4 | 2 | 1 |
5 | 3 | 1 |
6 | 4 | 1 |
7 | 4 | 0 |
8 | 4 | 0 |
After getting the lagid, how to use it continuously? First, only 0 meets the condition, so you can do a filter, and the result is removed as shown in the table xxx
below. Observe the 0 row below, how to distinguish the 0 in the 3 rows and the 0 in the 7 rows? Thinking of using a new grouping, rid will sort the same lagid and the same num, and add another column at the end, and group the same id-rid into a group
id | on one | lagid | rid | guide |
---|---|---|---|---|
1 | 1 | null xxx | ||
2 | 1 | 0 | 1 | 1 |
3 | 1 | 0 | 2 | 1 |
4 | 2 | 1 xxx | ||
5 | 3 | 1 xxx | ||
6 | 4 | 1 xxx | ||
7 | 4 | 0 | 1 | 6 |
8 | 4 | 0 | 2 | 6 |
-- 完整sql
## 解法1
SELECT num
FROM
(SELECT id,
num,
lagid,
(id-row_number() over(PARTITION BY num, lagid
ORDER BY id)) AS gid
FROM
(SELECT id,
num,
num- lag(num) (OVER PARTITION BY 1
ORDER BY id) AS lagid) tmp1
WHERE lagid=0 ) tmp2
GROUP BY num,
gid
HAVING count(*) >= 2
## 解法2
select
num,
gid,
count(1) as c
from
(
select
id,
num,
id-row_number() over(PARTITION BY num ORDER BY id) as gid
from
(select * from logs order by num,id) a
) b
group by num,gid
Later, I thought of a better one. In fact lag
, there is no need , and there is no need for order by
global sorting. The role of id is the same as date. It is generally used to cooperate row_number
to solve continuous problems, so it is row_number
essential. Then you can write it like this (God damn simple, is it? Don't think about it complicated):
SELECT num,
gid
FROM
(SELECT num,
id-row_number() OVER (PARTITION BY num
ORDER BY id) gid
FROM logs)
GROUP BY num,
gid
HAVING count(1) >= 3
3. Java problem description
First, give you an initial array arr. Then, every day you have to generate a new array based on the previous day's array. The array generated on the i day is obtained by performing the following operations on the array on the i-1 day: If an element is smaller than its left and right neighbors, the element is incremented by 1. If an element is larger than its left and right neighbors, then the element is decremented by 1.
The first and last elements never change.
After some time, you will find that the array will no longer change. Please return to the final array.
Example 1:
Input: [6,2,3,4]
Output: [6,3,3,4]
Explanation:
On the first day, the array changed from [6,2,3,4] to [6,3,3,4].
No more operations can be performed on this array.
Example 2:
Input: [1,6,3,4,3,5]
Output: [1,4,4,4,4,5]
Explanation:
On the first day, the array changed from [1,6,3,4,3,5] to [1,5,4,3,4,5].
The next day, the array changed from [1,5,4,3,4,5] to [1,4,4,4,4,5].
No more operations can be performed on this array.
3.3 Analysis and solution
-
First consider how to write a round of traversal. It should be very simple. The idea is to have a window of size 3.
-
Use a flag to mark whether the data has been changed in each round. Then the code is as follows:
public int[] get(int[] input) {
if (input == null || input.length <=2)
return input;
boolean flag = false;
do {
flag = false;
for (int i=1;i+1 < input.length;i++){
if (input[i] < input[i+1] && input[i] < input[i-1] ) {
input[i] +=1;
if (!flag)
flag = true;
}
if (input[i] > input[i+1] && input[i] > input[i-1] ) {
input[i] -=1;
if (!flag)
flag = true;
}
}
} while(flag)
return input;
}
Wu Xie, Xiao San Ye, a little rookie in the background, big data, and artificial intelligence.
Please pay attention to more