10個SQL技巧之四:找到連續的沒有間隙的最大系列的日期
現在我們正在進行宣告性程式設計,我們不關心維護任何狀態和記憶體中的計數器。我們希望以線上分析SQL的形式表達這一點。即考慮這些資料:
| LOGIN_TIME | | --------------------- | | 2014-03-18 05:37:13 | | 2014-03-16 08:31:47 | | 2014-03-16 06:11:17 | | 2014-03-16 05:59:33 | | 2014-03-15 11:17:28 | | 2014-03-15 10:00:11 | | 2014-03-15 07:45:27 | | 2014-03-15 07:42:19 | | 2014-03-14 09:38:12 | |
這沒有多大幫助。讓我們從時間戳中刪除小時。這很簡單:
SELECT DISTINCT cast(login_time AS DATE) AS login_date FROM logins WHERE user_id = :user_id |
輸出:
| LOGIN_DATE | | ------------ | | 2014-03-18 | | 2014-03-16 | | 2014-03-15 | | 2014-03-14 | |
現在,我們已經瞭解了視窗函式,讓我們只為每個日期新增一個簡單的行號:
SELECT login_date, row_number() OVER (ORDER BY login_date) FROM login_dates |
輸出:
| LOGIN_DATE | RN | | ------------ | ---- | | 2014-03-18 | 4 | | 2014-03-16 | 3 | | 2014-03-15 | 2 | | 2014-03-14 | 1 | |
還很容易。現在,如果不是單獨選擇這些值,我們會減去它們會發生什麼?
SELECT login_date - row_number() OVER (ORDER BY login_date) FROM login_dates |
我們得到這樣的結果:
| LOGIN_DATE | RN | GRP | | ------------ | ---- | ------------ | | 2014-03-18 | 4 | 2014-03-14 | | 2014-03-16 | 3 | 2014-03-13 | | 2014-03-15 | 2 | 2014-03-13 | | 2014-03-14 | 1 | 2014-03-13 | |
哇。有趣。所以,14 - 1 = 13,15 - 2 = 13,16 - 3 = 13,但是18 - 4 = 14.
這個動作代表一個簡單的判斷:
- ROW_NUMBER()沒有間隙。這就是它的定義方式
- 但是,我們的資料確實如此
因此,當我們從“連續”系列的非連續日期中減去“無間隙”系列連續整數時,我們將為連續日期的每個“無間隙”子系列獲得相同的日期,我們將再次獲得新的有間隙的日期系列。
這意味著我們現在只需GROUP BY這個任意日期值:
SELECT min(login_date), max(login_date), max(login_date) - min(login_date) + 1 AS length FROM login_date_groups GROUP BY grp ORDER BY length DESC |
我們已經完成了。已找到最大系列的連續日期,沒有間隙:
| MIN | MAX | LENGTH | |------------|------------|--------| | 2014-03-14 | 2014-03-16 | 3 | | 2014-03-18 | 2014-03-18 | 1 | |
完整查詢為:
WITH login_dates AS ( SELECT DISTINCT cast(login_time AS DATE) login_date FROM logins WHERE user_id = :user_id ), login_date_groups AS ( SELECT login_date, login_date - row_number() OVER (ORDER BY login_date) AS grp FROM login_dates ) SELECT min(login_date), max(login_date), max(login_date) - min(login_date) + 1 AS length FROM login_date_groups GROUP BY grp ORDER BY length DESC |
查詢本身確實非常簡單和優雅。你決不能以比這更精簡的方式實現一些命令式演算法。
相關文章
- SQL 獲取SQL Server中兩個日期之間的所有日期SQLServer
- SQL 獲取SQL Server中日期最近7天之間的所有日期SQLServer
- LeetCode-485-最大連續 1 的個數LeetCode
- leetcode —— 1004. 最大連續1的個數 IIILeetCode
- 直播原始碼,獲取兩個日期之間的所有日期原始碼
- UICollectionView間隙的坑UIView
- 怎麼去除img之間存在的間隔縫隙?
- hive生成連續的時間和連續的數Hive
- AI 四小龍之間沒有戰爭AI
- 連續子陣列的最大和陣列
- 一個連續動作空間的SAC的例子
- ORACLE 計算2個日期之間的天數Oracle
- SQL Server中的日期和時間:DATEADD()SQLServer
- leetcode力扣 1004. 最大連續1的個數 IIILeetCode力扣
- 表的連線是指在一個SQL語句中通過表與表之間的關連SQL
- 把起始日期與結束日期之間的所有日期返回
- Java 中,如何計算兩個日期之間的差距?Java
- 巧妙讓兩個span元素中間的空格不再有間隙
- 給出一個由[-100,100]之間整陣列成的陣列,求其相加和最大的連續子陣列 輸入 一個連續整陣列成的陣列 輸出 子陣列相加的最大值 樣例輸入 -......陣列
- win10 工作列只有時間沒有日期怎麼解決Win10
- 大資料開發-Hive-常用日期函式&&日期連續題sql套路大資料Hive函式SQL
- ios input 鍵盤收起頁面底部有間隙沒有自動還原iOS
- 最大連續子陣列和的實現陣列
- 6 個 Python 的日期時間庫Python
- SQL中的四種連線方式SQL
- 【演算法題解】485. 最大連續1的個數 - Java演算法Java
- 給定陣列中找到最大的兩個數陣列
- 有關於品牌軟文營銷的四個技巧
- JavaScript獲取兩個日期之間所有的日期JavaScript
- win10時間不顯示日期怎麼辦_win10電腦只顯示時間沒有日期如何處理Win10
- sql server日期格式 sqlserver的日期格式SQLServer
- 個人使用向5:連續時間表的應用
- JZ-030-連續子陣列的最大和陣列
- 推薦一個整合環境,appserv 沒找到有PHP5.3以上的。APPPHP
- CSS 帶有時間日期的新聞列表CSS
- JS-計算日期差值;計算日期之間的月數JS
- 間隙鎖
- 【leetcode】53. Maximum Subarray 連續子序列的最大和LeetCode