Office中國(guó)論壇/Access中國(guó)論壇

 找回密碼
 注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

返回列表 發(fā)新帖
查看: 3647|回復(fù): 1
打印 上一主題 下一主題

淺談數(shù)據(jù)庫(kù)開(kāi)發(fā)(三)——從寬表到存儲(chǔ)過(guò)程(之二)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
1#
發(fā)表于 2019-11-16 03:23:33 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
前面說(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)處理。
  1. declare @day0 date
  2. declare @day1 date
  3. declare @day2 date
  4. declare @day3 date
  5. declare @day4 date
  6. declare @day5 date
  7. declare @day6 date
  8. declare @day7 date
  9. declare @day8 date

  10. set @day0='2019-1-1'
  11. set @day1=DATEADD(day,1,@day0)
  12. set @day2=DATEADD(day,2,@day0)
  13. set @day3=DATEADD(day,3,@day0)
  14. set @day4=DATEADD(day,4,@day0)
  15. set @day5=DATEADD(day,5,@day0)
  16. set @day6=DATEADD(day,6,@day0)
  17. set @day7=DATEADD(day,7,@day0)
  18. set @day8=DATEADD(day,8,@day0)

  19. select 登錄時(shí)間
  20. ,SUM(day0) as day0
  21. ,SUM(day1) as day1
  22. ,SUM(day2) as day2
  23. ,SUM(day3) as day3
  24. ,SUM(day4) as day4
  25. ,SUM(day5) as day5
  26. ,SUM(day6) as day6
  27. ,SUM(day7) as day7
  28. ,SUM(day8) as day8
  29. from(
  30. select @day0 as 登錄時(shí)間
  31. ,count(distinct case when a.登錄時(shí)間=@day0 then a.用戶ID else null end) as day0
  32. ,count(distinct case when a.登錄時(shí)間=@day1 then a.用戶ID else null end) as day1
  33. ,count(distinct case when a.登錄時(shí)間=@day2 then a.用戶ID else null end) as day2
  34. ,count(distinct case when a.登錄時(shí)間=@day3 then a.用戶ID else null end) as day3
  35. ,count(distinct case when a.登錄時(shí)間=@day4 then a.用戶ID else null end) as day4
  36. ,count(distinct case when a.登錄時(shí)間=@day5 then a.用戶ID else null end) as day5
  37. ,count(distinct case when a.登錄時(shí)間=@day6 then a.用戶ID else null end) as day6
  38. ,count(distinct case when a.登錄時(shí)間=@day7 then a.用戶ID else null end) as day7
  39. ,count(distinct case when a.登錄時(shí)間=@day8 then a.用戶ID else null end) as day8
  40. from log_info a,(select distinct 用戶ID from log_info where 登錄時(shí)間=@day0) b
  41. where a.用戶ID=b.用戶ID and a.登錄時(shí)間>=@day0
  42. group by a.登錄時(shí)間
  43. union all
  44. select @day1 as 登錄時(shí)間
  45. ,0 as day0
  46. ,count(distinct case when a.登錄時(shí)間=@day1 then a.用戶ID else null end) as day1
  47. ,count(distinct case when a.登錄時(shí)間=@day2 then a.用戶ID else null end) as day2
  48. ,count(distinct case when a.登錄時(shí)間=@day3 then a.用戶ID else null end) as day3
  49. ,count(distinct case when a.登錄時(shí)間=@day4 then a.用戶ID else null end) as day4
  50. ,count(distinct case when a.登錄時(shí)間=@day5 then a.用戶ID else null end) as day5
  51. ,count(distinct case when a.登錄時(shí)間=@day6 then a.用戶ID else null end) as day6
  52. ,count(distinct case when a.登錄時(shí)間=@day7 then a.用戶ID else null end) as day7
  53. ,count(distinct case when a.登錄時(shí)間=@day8 then a.用戶ID else null end) as day8
  54. from log_info a,(select distinct 用戶ID from log_info where 登錄時(shí)間=@day1) b
  55. where a.用戶ID=b.用戶ID
  56. --新用戶
  57. and a.用戶ID not in(select 用戶ID from log_info c where c.登錄時(shí)間=@day0)
  58. group by a.登錄時(shí)間
  59. /*
  60. 這里僅用2個(gè)表進(jìn)行union all
  61. 以下從略。
  62. union all
  63. …………
  64. */
  65. ) a
  66. 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)該怎么建呢?欲知后事如何,且看下回分解。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享分享 分享淘帖 訂閱訂閱
2#
發(fā)表于 2021-10-11 10:19:33 | 只看該作者
學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則

QQ|站長(zhǎng)郵箱|小黑屋|手機(jī)版|Office中國(guó)/Access中國(guó) ( 粵ICP備10043721號(hào)-1 )  

GMT+8, 2025-7-13 08:09 , Processed in 0.079194 second(s), 25 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回復(fù) 返回頂部 返回列表