話說有一個日誌表,只有兩列,分別是連續id和num 至於啥意思,把它當金額把。如今想知道連續次數3次及以上的num,數據以下sql
id | num |
---|---|
1 | 1 |
2 | 1 |
3 | 1 |
4 | 2 |
5 | 3 |
6 | 4 |
7 | 4 |
8 | 4 |
那麼結果只有1,4知足條件,問這個sql該怎麼寫?數組
分析:題目簡單,沒有歧義,能看得懂,像連續幾回的這種問題必定是用到窗口函數,首先想到的是排名row_number
而後lag
怎麼體現連續呢,確定是須要用到一個排序的id,因爲題目給了id是連續遞增的,能夠省去row_number了函數
因此第一步,上lag,結果就是以下:大數據
id | num | 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 |
獲得lagid後,連續怎麼用呢,首先只有爲0的才知足條件,因此能夠作一個篩選,結果就以下表去掉xxx
的,下面觀察0的行,怎麼區分3 行的 0 和 7行的 0呢,想到使用新分組,rid 這樣就把lagid 相同,num相同的排序,最後再加一列,id-rid 相同的分爲一組人工智能
id | num | lagid | rid | gid |
---|---|---|---|---|
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
後面想到了更好的,其實不用lag
,也不用order by
全局排序,id 的做用和日期同樣,通常是用來配合row_number
來解決連續問題的,因此row_number
必不可少,那麼能夠這樣寫(神他媽簡單是否是,別想複雜了):spa
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
首先,給你一個初始數組 arr。而後,天天你都要根據前一天的數組生成一個新的數組。第 i 天所生成的數組,是由你對第 i-1 天的數組進行以下操做所得的:假如一個元素小於它的左右鄰居,那麼該元素自增 1。假如一個元素大於它的左右鄰居,那麼該元素自減 1。日誌
首、尾元素 永不 改變。code
過些時日,你會發現數組將會再也不發生變化,請返回最終所獲得的數組。排序
示例 1:get
輸入:[6,2,3,4]
輸出:[6,3,3,4]
解釋:
第一天,數組從 [6,2,3,4] 變爲 [6,3,3,4]。
沒法再對該數組進行更多操做。
示例 2:
輸入:[1,6,3,4,3,5]
輸出:[1,4,4,4,4,5]
解釋:
第一天,數組從 [1,6,3,4,3,5] 變爲 [1,5,4,3,4,5]。
次日,數組從 [1,5,4,3,4,5] 變爲 [1,4,4,4,4,5]。
沒法再對該數組進行更多操做。
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; }
吳邪,小三爺,混跡於後臺,大數據,人工智能領域的小菜鳥。
更多請關注