公交車上刷了一下知乎,看到一個問題:【怎么處理才能把左邊的表變成右邊?】
其實問題提問的很模糊,沒有業務描述,只說結果,接下來也就是按照答者的理解吧
答者認為該題需求:用戶連續訪問同一個頁面時,只保留最早的一條而已。
思路:我們冗余列來制作數據行之間的信息差,第一次我們需要明確數據的順序(知道前后),這里新增【用戶瀏覽時間序號】。
問題中消除重復,是為了消除同一個頁面連續訪問記錄只保留最早的一條,我們需要明確 用戶+頁面內的前后,
即【用戶瀏覽某頁面時間序號】, 即通過兩列信息差,我們可以找到自己想要的數據。
具體SQL邏輯如下: 第一步:在原始數據中通過冗余列制作信息差,作為數據篩選的依據:
select 用戶,頁面,瀏覽時間,
ROW_NUMBER() OVER(PARTITION BY 用戶 ORDER BY 瀏覽時間 ASC) AS 用戶瀏覽時間序號,
ROW_NUMBER() OVER(PARTITION BY 用戶,頁面 ORDER BY 瀏覽時間 ASC) AS 用戶瀏覽某頁面時間序號
from 用戶瀏覽日志
數據輸出:########### 結果集
用戶,頁面,瀏覽時間,用戶瀏覽時間序號,用戶瀏覽某頁面時間序號
甲,1,a,1,1
甲,1,b,2,2
甲,1,c,3,3
甲,2,d,4,1
甲,1,e,5,4
第二步,基於有信息差的結果集,來篩選出自己想要的數據:
select 用戶,頁面,瀏覽時間 from (select 用戶,頁面,瀏覽時間,
ROW_NUMBER() OVER(PARTITION BY 用戶 ORDER BY 瀏覽時間 ASC) AS 用戶瀏覽時間序號,
ROW_NUMBER() OVER(PARTITION BY 用戶,頁面 ORDER BY 瀏覽時間 ASC) AS 用戶瀏覽某頁面時間序號
from 用戶瀏覽日志) tt where tt.用戶瀏覽某頁面時間序號=1 or tt.用戶瀏覽時間序號<>tt.用戶瀏覽某頁面時間序號
最終輸出:########### 結果集
用戶,頁面,瀏覽時間
甲,1,a
甲,2,d
甲,1,e
------------ 上述答案有漏洞---------------------
然后:
同時過濾的數據條件修改為: where tt.頁面<> coalesce(tt.前一個瀏覽的頁面,0)
是不是很容易,只需要做兩次簡單的排序,就解決來問題。 遇到問題,要多思考,辦法肯定有,SQL一樣可以寫出花。
原文:https://www.zhihu.com/question/496875292/answer/2210351015