拉鏈表是數(shù)據(jù)倉(cāng)庫(kù)中特別重要的一種方式糕篇,它可以保留數(shù)據(jù)歷史變化的過(guò)程阀蒂,這里分享一下拉鏈表具體的開(kāi)發(fā)過(guò)程该窗。
維護(hù)歷史狀態(tài)弟蚀,以及最新?tīng)顟B(tài)數(shù)據(jù)的一種表,拉鏈表根據(jù)拉鏈粒度的不同酗失,實(shí)際上相當(dāng)于快照义钉,只不過(guò)做了優(yōu)化,去除了一部分不變的記錄规肴,通過(guò)拉鏈表可以很方便的還原出拉鏈時(shí)點(diǎn)的客戶記錄捶闸。
這里用商品價(jià)格的變化作為例子,具體的開(kāi)發(fā)過(guò)程要按實(shí)際的來(lái)拖刃,不能照搬代碼删壮,編程重要的是了解背后的思路和原理,而不是ctrl+c和ctrl+v兑牡。那對(duì)我們學(xué)習(xí)提升的幫助有限央碟,雖然可能對(duì)完成工作的效率幫助很大。
在開(kāi)始介紹之前均函,這里的數(shù)據(jù)倉(cāng)庫(kù)的環(huán)境是HIVE亿虽。
首先看看原始的數(shù)據(jù):
可以看到,原始的數(shù)據(jù)是每一個(gè)商品苞也,一條記錄洛勉,每一個(gè)商品,只保留最新的價(jià)格信息墩朦。這里的拉鏈表坯认,我們做到天粒度的。
我們這里的思路是這樣的氓涣,將最新的商品記錄插入歷史拉鏈表中牛哺,然后我們通過(guò)HIVE的窗口行數(shù),按照end_date排序劳吠,然后分別取下一條的sale_price和end_date引润,然后再判斷本條的價(jià)格和下一條的價(jià)格是否相等,如果是一樣的痒玩,那么就把end_date改為下一條的end_date,最后做去重處理淳附,然后就得到我們想要的數(shù)據(jù)了。
說(shuō)了這么多蠢古,我覺(jué)得還是把sql貼出來(lái)會(huì)好一些奴曙,代碼是最好的語(yǔ)言。
talk is cheap,show me the code草讶。
-- 商品原始表這里取名goods_table
select spu_id,
min(start_date) as start_date,
end_date as end_date,
sale_price
from
(select spu_id,
start_date,
if(sale_price = lead_sale_price,lead_end_date,end_date) as end_date,
sale_price
from
( select spu_id,
start_date,
end_date,
sale_price,
lead(sale_price,1,null) over(partition by spu_id order by end_date) as lead_sale_price,
lead(end_date) over(partition by spu_id order by end_date) as lead_end_date
from goods_table ) t) t
group by spu_id,
end_date,
sale_price ;
根據(jù)上面的代碼洽糟,跑出來(lái)的,就是我們想要的拉鏈表的數(shù)據(jù)了,看看最后的效果坤溃。
使用這種方式即可以記錄歷史拍霜,可以最大程度的節(jié)省存儲(chǔ),不會(huì)產(chǎn)生過(guò)多的冗余薪介。