只有光頭才能變強。html
文本已收錄至個人GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3yjava
最近在公司作了幾張報表,還記得剛開始要作報表的時候都快把SQL給忘光了(當時在廣州休假了1個月多,在實習期間也沒咋寫過SQL),回到公司的第一個需求就是作報表。git
因而我很不要臉地跟帶個人學長說:「SQL我好像忘光了,group 分組查詢好像都忘得差很少了,我得複習一下」。github
這篇文章來記錄一下我曾經忘掉的group查詢、join查詢等一些比較實用/經常使用的SQL正則表達式
group
查詢就是分組查詢,爲何要分組查詢?由於咱們想按某個維度進行統計。下面來看個圖:json
好比說,我想知道:天天Java3y這個公衆號的點擊量是多少。
按咱們人工而言,思路很簡單:把相同的天數以及公衆號名稱爲Java3y的數據找出來,再將每一個點擊量相加,就得出告終果了。數組
用上SQL咱們可能會這樣寫:函數
select name,time,sum(pv) as pv from xxx_table where name = 'Java3y' group by name,time
記得有一天,有個羣友在羣上問了一個問題:工具
其實他的需求很簡單:檢索出數據分組後時間最高的記錄。但他是這樣乾的:學習
order by
order by
後的記錄進行分組示例圖:
有的工具能夠支持這種的寫法:
select * from xxx_table group by name
這種寫法沒有被禁止,並能夠得出結果,好比獲得的結果是:
Java4y 20 7月15號 Java3y 30 7月15號
這種寫法實際上是不合理的,要知道的是:使用group by
分組統計以後,咱們的select 後面只能跟着group by 的字段,或者是聚合函數。
由於,咱們對數據進行了分組查詢,數據的分佈狀況,咱們是不關心的。
記住:先分組,後統計(先把數據歸類後,再對相同的數據進行統計)
去重是咱們常常會遇到的問題,打個比方說,因爲各類緣由(不論是業務上仍是說是髒數據),如今我有兩條重複的數據(除了ID,其他的字段都是相同的):
我這邊只但願留下某一條記錄做爲查詢結果就行了,咱們能夠寫下如下的SQL:
select * from user where id in( select min(id) from user where name = 'Java3y' and pv = 20 and time='7-25' group by name,pv,time; )
上面這條SQL是很是很是實用的,除了我說的去重之外,其實咱們能夠再」思考「一下:
group by
分組統計以後,咱們的select 後面只能跟着group by 的字段,或者是聚合函數。group by
了之後,還想要查詢結果中包含group by
以外的字段(通常狀況下,咱們都不可能將group by 涵蓋全部的字段),咱們就能夠上面那樣,將查詢後的結果做爲子查詢,放在外部查詢的where 子句後,這樣外部查詢是能夠select 出其餘字段的。(SQL寫得比較少的朋友可能沒什麼感觸啊,但我但願上面那種寫法你們可以記住,之後必定會遇到相似的狀況的)
join查詢不知道你們在剛學的時候是怎麼理解的,反正我當初好像就挺迷迷糊糊的。我以爲join查詢能夠簡單理解成這樣:我想要的查詢結果,一張表搞不掂,那我就join另外一張表
好比說,如今我有兩張的表:
如今我想知道在7月25號時:每一個公衆號的點擊量、公衆號名稱、號主名稱、公衆號的建立日期
那join其實就是把兩張表合起來的一個操做:
兩張表合併起來之後咱們就會發現,這張「大表」就含有這兩張表的全部字段啦,那我想要什麼都有了!
值得注意的是:在join的時候,會產生笛卡爾積(至於什麼是笛卡爾積我這裏就不說了,反正咱們要記住的是join表時必定要寫關聯條件去除笛卡爾積)
另外,left join
和right join
也是咱們常常用到,若是咱們單純寫join
關鍵字,那會被當成是inner join
。下面我簡單解釋一下:
inner join
的話,只有符合關聯條件的數據纔會存在最大表中left join
的話,即使關聯條件不符合,左邊表的數據必定會存在大表中right join
的話,即使關聯條件不符合,右邊表的數據必定會存在大表中看下面的圖:
此時咱們的兩張表關聯的條件是「公衆號」 :若是是inner join
,那麼最後咱們的表只有兩條記錄。若是是left join
,那麼最後咱們的表有三條數據。若是是right join
,那麼咱們最後的表只有兩條數據
SQL中的case when then else end用法其實跟咱們程序語言中的if-else
非常相似,在寫SQL的時候也經常會用到。
我用得比較多的語法以下:
CASE WHEN sex = '1' THEN '男' WHEN sex = '2' THEN '女' ELSE '其餘' END
在when後面能夠跟多個表達式,好比說:
CASE WHEN sex = '1' and name ='Java3y' THEN '男' WHEN sex = '2' and name ='Java4y' THEN '女' ELSE '其餘' END
若是要爲case when
表達式取別名,在end
關鍵字後邊直接加就行了
更多用法詳情參考:
我這邊會有這種狀況:將json數據存到MySQL上。我去網上搜了一下以及問了同事,爲何要將json存到MySQL的字段上時,他們的答覆都差很少:
參考資料:
我這邊作報表通常來hive或presto上搞的,因此解析json的也是在那上面。
hive解析json函數:
get_json_object(param1,'$.param2') -- 若是是數組 get_json_object(xjson,'$.[0].param2')
presto 對json的處理函數:
-- 數組 (去除第index個json) json_array_get(xjson,index) -- 單個jsoin對象 json_extract(xjson,'$.param2')
參考資料:
昨天/近7天/本月按照這種指標來查詢也是很是常見的:
昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 時間字段名) <= 1 7天 SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(時間字段名) 近30天 SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(時間字段名) 本月 SELECT * FROM 表名 WHERE DATE_FORMAT( 時間字段名, '%Y%m' ) = DATE_FORMAT( CURDATE( ) , '%Y%m' ) 上一月 SELECT * FROM 表名 WHERE PERIOD_DIFF( date_format( now( ) , '%Y%m' ) , date_format( 時間字段名, '%Y%m' ) ) =1
在presto中使用時間格式,須要明確寫出關鍵字timestamp
,好比:
select supplier,count(id) from xxx_table where sendtime >= timestamp '2019-06-01'
參考資料:
這裏我簡單整理一下我最近用過函數:
length --計算字符串長度 concat --鏈接兩個字符串 substring -- 截取字符串 count -- 統計數量 max -- 最大 min -- 最小 sum -- 合計 floor/ceil --...數學函數
再來分享一下最近遇到的一個需求,如今有的數據以下:
【Java3y簡單】快樂學習 【Java3y簡單】快樂學習渣渣 【Java3y通俗易懂】簡單學 【Java3y通俗易懂】簡單學芭芭拉 【Java3y平易近人】無聊學 【Java3y初學者】枯燥學 【Java3y初學者】枯燥學呱呱 【Java3y大數據】欣慰學 【Java3y學習】巴拉巴拉學 【Java3y學習】巴拉巴拉學哈哈 【Java3y好】雨女無瓜學
如今我統計出【】括號裏邊出現的頻次,好比說:Java3y通俗易懂
出現的頻次是多少。當時一直都沒想到好的思路,都快要搜「SQL 正則表達式 快速入門」了,請教了一下同事,同事很快就寫出來了:
select substring_index(left(title , INSTR(title , '】') -1 ) , '【',-1) FROM `xxx_table`
哇~,awesome
樂於輸出乾貨的Java技術公衆號:Java3y。公衆號內有200多篇原創技術文章、海量視頻資源、精美腦圖,關注便可獲取!
以爲個人文章寫得不錯,點贊!