亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > PostgreSQL > 正文

介紹PostgreSQL中的Lateral類型

2020-03-12 23:53:39
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了介紹PostgreSQL中的Lateral類型,Lateral是PostgreSQL9.3版本以來加入的內置類型,需要的朋友可以參考下

PostgreSQL 9.3 用了一種新的聯合類型! Lateral聯合的推出比較低調,但它實現了之前需要使用編寫程序才能獲得的強大的新查詢. 在本文中, 我將會介紹一個在 PostgreSQL 9.2 不可能被實現的渠道轉換分析.

什么是 LATERAL 聯合?

對此的最佳描述在文檔中可選 FROM 語句清單的底部:

LATERAL 關鍵詞可以在前綴一個 SELECT FROM 子項. 這能讓 SELECT 子項在FROM項出現之前就引用到FROM項中的列. (沒有 LATERAL 的話, 每一個 SELECT 子項彼此都是獨立的,因此不能夠對其它的 FROM 項進行交叉引用.)

當一個 FROM 項包含 LATERAL 交叉引用的時候,查詢的計算過程如下: 對于FROM像提供給交叉引用列的每一行,或者多個FROM像提供給引用列的行的集合, LATERAL 項都會使用行或者行的集合的列值來進行計算. 計算出來的結果集像往常一樣被加入到聯合查詢之中. 這一過程會在列的來源表的行或者行的集合上重復進行.

這種計算有一點密集。你可以比較松散的將 LATERAL 聯合理解作一個 SQL 的foreach 選擇, 在這個循環中 PostgreSQL 將循環一個結果集中的每一行,并將那一行作為參數來執行一次子查詢的計算.

我們可以用這個來干些什么?

看看下面這個用來記錄點擊事件的表結構:

 

 
  1. CREATE TABLE event ( 
  2. user_id BIGINT
  3. event_id BIGINT
  4. time BIGINT NOT NULL
  5. data JSON NOT NULL
  6. PRIMARY KEY (user_id, event_id) 

每一個事件都關聯了一個用戶,擁有一個ID,一個時間戳,還有一個帶有事件屬性的JSON blob. 在堆中,這些屬性可能包含一次點擊的DOM層級, 窗口的標題,會話引用等等信息.

加入我們要優化我們的登錄頁面以增加注冊. 第一步就是要計算看看我們的哪個渠道轉換上正在丟失用戶.

介紹PostgreSQL中的Lateral類型

示例:一個注冊流程的個步驟之間的渠道轉換率.

假設我們已經在前端配備的裝置,來沿著這一流程來記錄事件日志,所有的數據都會保存到上述的事件數據表中.[1] 最開始的問題是,我們要計算有多少人查看了我們的主頁,而他們之中有百分之多少在那次查看了主頁之后的兩個星期之內輸入了驗證信息. 如果我們使用 PostgreSQL 較老的版本, 我們可能需要使用PL/pgSQL這一PostgreSQL內置的過程語言 來編寫一些定制的函數. 而在 9.3 中, 我們就可以使用一個 lateral 聯合,只用一個搞笑的查詢就能計算出結果,不需要任何擴展或者 PL/pgSQL.

 

 
  1. SELECT 
  2. user_id, 
  3. view_homepage, 
  4. view_homepage_time, 
  5. enter_credit_card, 
  6. enter_credit_card_time 
  7. FROM ( 
  8. -- Get the first time each user viewed the homepage. 
  9. SELECT 
  10. user_id, 
  11. AS view_homepage, 
  12. min(timeAS view_homepage_time 
  13. FROM event 
  14. WHERE 
  15. data->>'type' = 'view_homepage' 
  16. GROUP BY user_id 
  17. ) e1 LEFT JOIN LATERAL ( 
  18. -- For each row, get the first time the user_id did the enter_credit_card 
  19. -- event, if one exists within two weeks of view_homepage_time. 
  20. SELECT 
  21. AS enter_credit_card, 
  22. time AS enter_credit_card_time 
  23. FROM event 
  24. WHERE 
  25. user_id = e1.user_id AND 
  26. data->>'type' = 'enter_credit_card' AND 
  27. time BETWEEN view_homepage_time AND (view_homepage_time + 1000*60*60*24*14) 
  28. ORDER BY time 
  29. LIMIT 1 
  30. ) e2 ON true 

沒有人會喜歡30多行的SQL查詢,所以讓我們將這些SQL分成片段來分析。第一塊是一段普通的 SQL:

 

 
  1. SELECT 
  2. user_id, 
  3. AS view_homepage, 
  4. min(timeAS view_homepage_time 
  5. FROM event 
  6. WHERE 
  7. data->>'type' = 'view_homepage' 
  8. GROUP BY user_id 

也就是要獲取到每個用戶最開始觸發 view_homepage 事件的時間. 然后我們的 lateral 聯合就可以讓我們迭代結果集的每一行,并會在接下來執行一次參數化的子查詢. 這就等同于針對結果集的每一行都要執行一邊下面的這個查詢:

 

 
  1. SELECT 
  2. AS enter_credit_card, 
  3. time AS enter_credit_card_time 
  4. FROM event 
  5. WHERE 
  6. user_id = e1.user_id AND 
  7. data->>'type' = 'enter_credit_card' AND 
  8. time BETWEEN view_homepage_time AND (view_homepage_time + 1000*60*60*24*14) 
  9. ORDER BY time 
  10. LIMIT 1 

例如,對于每一個用戶,要獲取他們在觸發 view_homepage_time 事件后的兩星期內觸發 enter_credit_card 事件的時間. 因為這是一個lateral聯合,我們的子查詢就可以從之前的子查詢出引用到 view_homepage_time 結果集. 否則,子查詢就只能單獨執行,而沒辦法訪問到另外一個子查詢所計算出來的結果集.

之后哦我們整個封裝成一個select,它會返回像下面這樣的東西:

 

 
  1. user_id | view_homepage | view_homepage_time | enter_credit_card | enter_credit_card_time 
  2. ---------+---------------+--------------------+-------------------+------------------------ 
  3. 567 | 1 | 5234567890 | 1 | 5839367890 
  4. 234 | 1 | 2234567890 | | 
  5. 345 | 1 | 3234567890 | | 
  6. 456 | 1 | 4234567890 | | 
  7. 678 | 1 | 6234567890 | | 
  8. 123 | 1 | 1234567890 | | 
  9. ...  

因為這是一個左聯合,所以查詢結果集中會有不匹配 enter_credit_card 事件的行,只要有 view_homepage 事件就行. 如果我們匯總所有的數值列,就會得到渠道轉換的一個清晰匯總:

 

 
  1. SELECT 
  2. sum(view_homepage) AS viewed_homepage, 
  3. sum(enter_credit_card) AS entered_credit_card 
  4. FROM ( 
  5. -- Get the first time each user viewed the homepage. 
  6. SELECT 
  7. user_id, 
  8. AS view_homepage, 
  9. min(timeAS view_homepage_time 
  10. FROM event 
  11. WHERE 
  12. data->>'type' = 'view_homepage' 
  13. GROUP BY user_id 
  14. ) e1 LEFT JOIN LATERAL ( 
  15. -- For each (user_id, view_homepage_time) tuple, get the first time that 
  16. -- user did the enter_credit_card event, if one exists within two weeks. 
  17. SELECT 
  18. AS enter_credit_card, 
  19. time AS enter_credit_card_time 
  20. FROM event 
  21. WHERE 
  22. user_id = e1.user_id AND 
  23. data->>'type' = 'enter_credit_card' AND 
  24. time BETWEEN view_homepage_time AND (view_homepage_time + 1000*60*60*24*14) 
  25. ORDER BY time 
  26. LIMIT 1 
  27. ) e2 ON true 

… 它會輸出:

 

  
  1. viewed_homepage | entered_credit_card 
  2. -----------------+--------------------- 
  3. 827 | 10 

我們可以向這個渠道中填入帶有更多lateral聯合的中間步驟,來得到流程中我們需要重點改進的部分. 讓我們在查看主頁和輸入驗證信息之間加入對使用示例步驟的查詢.

 

 
  1. SELECT 
  2. sum(view_homepage) AS viewed_homepage, 
  3. sum(use_demo) AS use_demo, 
  4. sum(enter_credit_card) AS entered_credit_card 
  5. FROM ( 
  6. -- Get the first time each user viewed the homepage. 
  7. SELECT 
  8. user_id, 
  9. AS view_homepage, 
  10. min(timeAS view_homepage_time 
  11. FROM event 
  12. WHERE 
  13. data->>'type' = 'view_homepage' 
  14. GROUP BY user_id 
  15. ) e1 LEFT JOIN LATERAL ( 
  16. -- For each row, get the first time the user_id did the use_demo 
  17. -- event, if one exists within one week of view_homepage_time. 
  18. SELECT 
  19. user_id, 
  20. AS use_demo, 
  21. time AS use_demo_time 
  22. FROM event 
  23. WHERE 
  24. user_id = e1.user_id AND 
  25. data->>'type' = 'use_demo' AND 
  26. time BETWEEN view_homepage_time AND (view_homepage_time + 1000*60*60*24*7) 
  27. ORDER BY time 
  28. LIMIT 1 
  29. ) e2 ON true LEFT JOIN LATERAL ( 
  30. -- For each row, get the first time the user_id did the enter_credit_card 
  31. -- event, if one exists within one week of use_demo_time. 
  32. SELECT 
  33. AS enter_credit_card, 
  34. time AS enter_credit_card_time 
  35. FROM event 
  36. WHERE 
  37. user_id = e2.user_id AND 
  38. data->>'type' = 'enter_credit_card' AND 
  39. time BETWEEN use_demo_time AND (use_demo_time + 1000*60*60*24*7) 
  40. ORDER BY time 
  41. LIMIT 1 
  42. ) e3 ON true 

這樣就會輸出:

 

 
  1. viewed_homepage | use_demo | entered_credit_card 
  2. -----------------+----------+--------------------- 
  3. 827 | 220 | 86  

從查看主頁到一周之內使用demo,再到一周以內向其輸入信用卡信息,這就向我們提供了三個步驟的通道轉換. 從此,功能強大的 PostgreSQL 使得我們可以深入分析這些數據結果集,并對我們的網站性能進行整體的分析. 接著我們可能會有下面這些問題要解決:

使用demo是否能增加注冊的可能性?

通過廣告找到我們主頁的用戶是否同來自其他渠道的用戶擁有相同的轉換率?

轉換率會跟隨不同的 A/B 測試變量發生怎樣的變化?

這些問題的答案會直接影響到產品的改進,它們可以從 PostgreSQL 數據庫中找到答案,因為現在它支持 lateral 聯合.

沒有 lateral 聯合,我們就只能借助 PL/pgSQL 來做這些分析?;蛘撸绻覀兊臄祿苄?,我們可能就不會碰這些復雜、低效的查詢. 在一項探索性數據研究使用場景下,你可能只是將數據從 PostgreSQL 里面抽取出來,并使用你所選擇的腳本語言來對其進行分析。但是其實還存在更強大的理由來用SQL表述這些問題, 特別是如果你正想要把整個全封裝到一套易于理解的UI中,并向非技術型用戶發布功能 的時候.

注意這些查詢可以被優化,以變得更加高效. 在本例中,如果我們在 (user_id, (data->>'type'), time)上創建一個btree索引, 我們只用一次索引查找就能針對每一個用戶計算每一個渠道步驟. 如果你使用的是SSD,在上面做查找花費是很小的,那這就足夠了。而如果不是,你就可能需要用稍微不同的手段來圖示化你的數據,詳細的內容我會留到另外一篇文章之中進行介紹.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
午夜精品美女自拍福到在线| 欧美美女操人视频| 国产精品久久久久77777| 欧美国产日韩一区二区在线观看| 亚洲无亚洲人成网站77777| 日本伊人精品一区二区三区介绍| 日韩美女在线观看一区| 日韩一区二区三区国产| 国产视频精品一区二区三区| 欧美日韩在线观看视频小说| 国产亚洲精品久久久久久| 浅井舞香一区二区| 欧美老女人性生活| 91丨九色丨国产在线| 欧美在线观看视频| 日韩成人中文字幕| 欧美亚洲第一区| 日韩电影大全免费观看2023年上| 奇米四色中文综合久久| 777精品视频| 欧美黑人一级爽快片淫片高清| 疯狂欧美牲乱大交777| 久久久黄色av| 影音先锋日韩有码| 日韩av一区在线观看| 国产精品高清网站| 最近2019年中文视频免费在线观看| 日韩av成人在线| 2019最新中文字幕| 国产日韩中文字幕在线| 日韩免费av一区二区| 亚洲深夜福利视频| 午夜精品福利在线观看| 在线免费看av不卡| 中文字幕视频在线免费欧美日韩综合在线看| 精品国产一区二区三区久久久狼| 69**夜色精品国产69乱| 日韩精品一二三四区| 国内精品模特av私拍在线观看| 欧美日韩国产成人在线观看| 国产精选久久久久久| 高清日韩电视剧大全免费播放在线观看| 国内精品在线一区| 久久久噜久噜久久综合| 国产在线精品一区免费香蕉| 97人人模人人爽人人喊中文字| 成人免费视频在线观看超级碰| 亚洲一区二区三区乱码aⅴ蜜桃女| 色播久久人人爽人人爽人人片视av| 国产精品久久久久久久久久| 午夜精品一区二区三区在线视频| 欧洲中文字幕国产精品| 久久成人av网站| 亚洲欧美成人在线| 亚洲成人精品视频| 久久琪琪电影院| 日本在线精品视频| 日本欧美爱爱爱| 国产亚洲精品美女久久久久| 日韩电影中文字幕在线观看| 中文字幕一区日韩电影| 亚洲美女av电影| 日韩免费看的电影电视剧大全| 色综合五月天导航| 久久久久久中文| 欧美一区二区三区图| 国产中文字幕91| 欧美中文字幕在线视频| 欧美区二区三区| xx视频.9999.com| 亚洲国产欧美一区二区丝袜黑人| 国产成+人+综合+亚洲欧美丁香花| 亚洲欧美中文另类| 国产日韩欧美黄色| 91视频国产高清| 欧美人交a欧美精品| 精品国产成人av| 中文字幕亚洲无线码在线一区| 欧美激情国产日韩精品一区18| 青青草国产精品一区二区| 亚洲人a成www在线影院| 日韩av综合中文字幕| 欧美成人黄色小视频| 久久久久久一区二区三区| 欧美电影在线播放| 亚洲精品99久久久久中文字幕| 亚洲深夜福利视频| 精品久久中文字幕| 九色精品免费永久在线| 97精品在线视频| 久久91亚洲精品中文字幕奶水| 久久婷婷国产麻豆91天堂| zzijzzij亚洲日本成熟少妇| 中文字幕在线看视频国产欧美在线看完整| 性欧美办公室18xxxxhd| 国产91对白在线播放| 久久久久久久久久久国产| 国产精品白丝jk喷水视频一区| 亚洲aa中文字幕| 亚洲一二在线观看| 欧美黑人一区二区三区| 最近2019免费中文字幕视频三| 欧美性猛交xxxxx免费看| 久久精品色欧美aⅴ一区二区| 国产激情视频一区| 久久香蕉频线观| 亚洲成人黄色网址| 中文字幕免费精品一区高清| 国产视频精品xxxx| 国产精品ⅴa在线观看h| 国产剧情久久久久久| 少妇久久久久久| 久久成人精品一区二区三区| 日韩专区在线播放| 亚洲第一福利网| 国内精品免费午夜毛片| 全亚洲最色的网站在线观看| 色一区av在线| 亚洲女在线观看| 久久全球大尺度高清视频| 国产精品va在线| 欧美日韩国产精品一区二区三区四区| 亚洲乱码国产乱码精品精天堂| 国产精品丝袜白浆摸在线| 国产999精品久久久影片官网| 欧美午夜激情视频| 亚洲码在线观看| 久久国产精品网站| 高清欧美电影在线| 琪琪第一精品导航| 在线视频国产日韩| 久久久久一本一区二区青青蜜月| 亚洲国产精品一区二区久| 麻豆国产精品va在线观看不卡| 日韩经典中文字幕在线观看| 欧美高清一级大片| 91豆花精品一区| 亚洲黄色在线看| 欧美黑人xxxⅹ高潮交| 国产精品极品在线| 亚洲久久久久久久久久| 国产精品视频地址| 日韩欧美精品在线观看| 国产欧美在线视频| 欧美精品少妇videofree| 欧美日韩免费一区| 久久男人的天堂| 日韩精品极品视频免费观看| 国内精品久久久久久影视8| 国产精品亚洲欧美导航| 国产午夜精品麻豆| 最近2019年中文视频免费在线观看| 国产精品日韩在线一区| 亚洲视频视频在线| 岛国av一区二区在线在线观看| 色噜噜国产精品视频一区二区| 精品亚洲夜色av98在线观看| 亚洲国产精品美女| 久久天堂电影网| 日韩成人在线视频| 亚洲人成电影在线| 欧美一级片免费在线| 亚洲人成网在线播放| 黄色成人av网|