技術(shù) 點(diǎn)
- 技術(shù)
- 點(diǎn)
- V幣
- 點(diǎn)
- 積分
- 22847
|
前面說(shuō)了。按這種寫法,至少要union all七八個(gè)子句。且不說(shuō)容易出錯(cuò),萬(wàn)一某天,甲方爸爸說(shuō),我今天不想看1月1日的數(shù)據(jù),我想看1月8日開(kāi)始的留存率。。。。估計(jì)這時(shí)候你就一波操作猛如虎,“查找,替換!毕劝1月1日的改成1月8日,然后把1月2日的改成1月9日……如此類推。過(guò)幾天,甲方爸爸又說(shuō),我想看1月3日一個(gè)星期內(nèi)的留存率。。。。于是你心里一萬(wàn)匹草泥馬奔騰而過(guò),腹誹不已,“這特么還有完沒(méi)完?”,但你不敢聲張,只好臉上笑嘻嘻,心里MMP。
經(jīng)過(guò)幾番折騰,你決定用變量來(lái)處理。
- declare @day0 date
- declare @day1 date
- declare @day2 date
- declare @day3 date
- declare @day4 date
- declare @day5 date
- declare @day6 date
- declare @day7 date
- declare @day8 date
- set @day0='2019-1-1'
- set @day1=DATEADD(day,1,@day0)
- set @day2=DATEADD(day,2,@day0)
- set @day3=DATEADD(day,3,@day0)
- set @day4=DATEADD(day,4,@day0)
- set @day5=DATEADD(day,5,@day0)
- set @day6=DATEADD(day,6,@day0)
- set @day7=DATEADD(day,7,@day0)
- set @day8=DATEADD(day,8,@day0)
- select 登錄時(shí)間
- ,SUM(day0) as day0
- ,SUM(day1) as day1
- ,SUM(day2) as day2
- ,SUM(day3) as day3
- ,SUM(day4) as day4
- ,SUM(day5) as day5
- ,SUM(day6) as day6
- ,SUM(day7) as day7
- ,SUM(day8) as day8
- from(
- select @day0 as 登錄時(shí)間
- ,count(distinct case when a.登錄時(shí)間=@day0 then a.用戶ID else null end) as day0
- ,count(distinct case when a.登錄時(shí)間=@day1 then a.用戶ID else null end) as day1
- ,count(distinct case when a.登錄時(shí)間=@day2 then a.用戶ID else null end) as day2
- ,count(distinct case when a.登錄時(shí)間=@day3 then a.用戶ID else null end) as day3
- ,count(distinct case when a.登錄時(shí)間=@day4 then a.用戶ID else null end) as day4
- ,count(distinct case when a.登錄時(shí)間=@day5 then a.用戶ID else null end) as day5
- ,count(distinct case when a.登錄時(shí)間=@day6 then a.用戶ID else null end) as day6
- ,count(distinct case when a.登錄時(shí)間=@day7 then a.用戶ID else null end) as day7
- ,count(distinct case when a.登錄時(shí)間=@day8 then a.用戶ID else null end) as day8
- from log_info a,(select distinct 用戶ID from log_info where 登錄時(shí)間=@day0) b
- where a.用戶ID=b.用戶ID and a.登錄時(shí)間>=@day0
- group by a.登錄時(shí)間
- union all
- select @day1 as 登錄時(shí)間
- ,0 as day0
- ,count(distinct case when a.登錄時(shí)間=@day1 then a.用戶ID else null end) as day1
- ,count(distinct case when a.登錄時(shí)間=@day2 then a.用戶ID else null end) as day2
- ,count(distinct case when a.登錄時(shí)間=@day3 then a.用戶ID else null end) as day3
- ,count(distinct case when a.登錄時(shí)間=@day4 then a.用戶ID else null end) as day4
- ,count(distinct case when a.登錄時(shí)間=@day5 then a.用戶ID else null end) as day5
- ,count(distinct case when a.登錄時(shí)間=@day6 then a.用戶ID else null end) as day6
- ,count(distinct case when a.登錄時(shí)間=@day7 then a.用戶ID else null end) as day7
- ,count(distinct case when a.登錄時(shí)間=@day8 then a.用戶ID else null end) as day8
- from log_info a,(select distinct 用戶ID from log_info where 登錄時(shí)間=@day1) b
- where a.用戶ID=b.用戶ID
- --新用戶
- and a.用戶ID not in(select 用戶ID from log_info c where c.登錄時(shí)間=@day0)
- group by a.登錄時(shí)間
- /*
- 這里僅用2個(gè)表進(jìn)行union all
- 以下從略。
- union all
- …………
- */
- ) a
- group by 登錄時(shí)間
復(fù)制代碼 這時(shí)候,你發(fā)現(xiàn),只需要改下@day0的值,就能隨時(shí)算出留存客戶數(shù)了。你開(kāi)始為自己的聰明鼓掌。但你還是隱隱有些擔(dān)憂,F(xiàn)在甲方爸爸只是想看一個(gè)星期的數(shù)據(jù),你已經(jīng)寫得這么復(fù)雜了,萬(wàn)一某天他心血來(lái)潮要看一個(gè)月的呢?此外,還有一個(gè)問(wèn)題,數(shù)據(jù)都不是現(xiàn)成的。每次修改條件,就必須重新計(jì)算。你覺(jué)得這可能會(huì)影響體驗(yàn)。那么,這個(gè)是否可以做成一張表,每次運(yùn)行時(shí)把數(shù)據(jù)插入再展示呢?
于是,你開(kāi)始在論壇里翻到了roych寫的那篇帖子,終于體會(huì)到寬表的好處了。那么表結(jié)構(gòu)該怎么確定呢?是不是可以按結(jié)果表那樣做?如果按那樣建表的話,那么主鍵顯然不好確定。用第一列的日期作為主鍵看起來(lái)沒(méi)什么問(wèn)題,
但實(shí)際上,你會(huì)發(fā)現(xiàn),這個(gè)根本就不具備主鍵的氣質(zhì)。這個(gè)字段來(lái)源于一個(gè)常量。——雖然看起來(lái)像是變量,但到了底層,它每一行都是一樣的。——如果真的采取這樣的方案,有沒(méi)有問(wèn)題?
當(dāng)然沒(méi)有問(wèn)題。前面我們不用存儲(chǔ)過(guò)程都能寫出來(lái),何況現(xiàn)在改為存儲(chǔ)過(guò)程,理論上應(yīng)該更簡(jiǎn)單才對(duì)。但由于不存在主鍵或者唯一索引的要求,因此,原先的SQL語(yǔ)句也就談不上優(yōu)化了。
那么為了優(yōu)化SQL語(yǔ)句,這寬表應(yīng)該怎么建呢?欲知后事如何,且看下回分解。
|
|