在工做中經常使用到的SQL

前言

只有光頭才能變強。html

文本已收錄至個人GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3yjava

最近在公司作了幾張報表,還記得剛開始要作報表的時候都快把SQL給忘光了(當時在廣州休假了1個月多,在實習期間也沒咋寫過SQL),回到公司的第一個需求就是作報表。git

因而我很不要臉地跟帶個人學長說:「SQL我好像忘光了,group 分組查詢好像都忘得差很少了,我得複習一下」。github

這篇文章來記錄一下我曾經忘掉的group查詢、join查詢等一些比較實用/經常使用的SQL正則表達式

  • 本文主打通俗易懂,不涵蓋任何優化(適合新手觀看)

1、回顧group 查詢

group查詢就是分組查詢,爲何要分組查詢?由於咱們想按某個維度進行統計。下面來看個圖:json

如今個人數據以下

好比說,我想知道:天天Java3y這個公衆號的點擊量是多少。按咱們人工而言,思路很簡單:把相同的天數以及公衆號名稱爲Java3y的數據找出來,再將每一個點擊量相加,就得出告終果了。數組

步驟

用上SQL咱們可能會這樣寫:函數

select name,time,sum(pv) as pv  
from xxx_table 
where name = 'Java3y' group by name,time

1.1 group 查詢可能存在的誤解

記得有一天,有個羣友在羣上問了一個問題:工具

羣裏邊的一個問題

其實他的需求很簡單:檢索出數據分組後時間最高的記錄。但他是這樣乾的:學習

  1. 把先按照時間 order by
  2. order by後的記錄進行分組

示例圖:

羣裏面的一個圖

1.2 形成這個誤解的可能緣由

有的工具能夠支持這種的寫法:

select * from xxx_table group by name

這種寫法沒有被禁止,並能夠得出結果,好比獲得的結果是:

Java4y    20  7月15號
Java3y    30  7月15號

這種寫法實際上是不合理的,要知道的是:使用group by分組統計以後,咱們的select 後面只能跟着group by 的字段,或者是聚合函數。

group by規則

由於,咱們對數據進行了分組查詢,數據的分佈狀況,咱們是不關心的

記住:先分組,後統計(先把數據歸類後,再對相同的數據進行統計)

1.3 group查詢最經常使用的SQL

去重是咱們常常會遇到的問題,打個比方說,因爲各類緣由(不論是業務上仍是說是髒數據),如今我有兩條重複的數據(除了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寫得比較少的朋友可能沒什麼感觸啊,但我但願上面那種寫法你們可以記住,之後必定會遇到相似的狀況的)

2、回顧join查詢

join查詢不知道你們在剛學的時候是怎麼理解的,反正我當初好像就挺迷迷糊糊的。我以爲join查詢能夠簡單理解成這樣:我想要的查詢結果,一張表搞不掂,那我就join另外一張表

好比說,如今我有兩張的表:

第一張表

第二張表

如今我想知道在7月25號時:每一個公衆號的點擊量、公衆號名稱、號主名稱、公衆號的建立日期

  • 顯然,咱們會發現一張表搞不掂啊,某些數據要依賴於另外一張表才能把數據"完整"展現出來

那join其實就是把兩張表合起來的一個操做:

join其實就是一個合併的操做

兩張表合併起來之後咱們就會發現,這張「大表」就含有這兩張表的全部字段啦,那我想要什麼都有了!

值得注意的是:在join的時候,會產生笛卡爾積(至於什麼是笛卡爾積我這裏就不說了,反正咱們要記住的是join表時必定要寫關聯條件去除笛卡爾積

另外,left joinright join也是咱們常常用到,若是咱們單純寫join關鍵字,那會被當成是inner join 。下面我簡單解釋一下:

  • 上面說了,在join的時候必定要寫關聯條件,若是是inner join的話,只有符合關聯條件的數據纔會存在最大表中
  • 若是是left join的話,即使關聯條件不符合,左邊表的數據必定會存在大表中
  • 若是是right join的話,即使關聯條件不符合,右邊表的數據必定會存在大表中

看下面的圖:

join

此時咱們的兩張表關聯的條件是「公衆號」 :若是是inner join,那麼最後咱們的表只有兩條記錄。若是是left join ,那麼最後咱們的表有三條數據。若是是right join,那麼咱們最後的表只有兩條數據

3、回顧case when

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 關鍵字後邊直接加就行了

更多用法詳情參考:

4、一些經常使用的函數

4.1 hive和presto解析json

我這邊會有這種狀況:將json數據存到MySQL上。我去網上搜了一下以及問了同事,爲何要將json存到MySQL的字段上時,他們的答覆都差很少:

  • 在MySQL存json數據,這樣方便擴展啊。若是那些字段不須要用到索引,改動比較頻繁,你又不想改動表的結構,那能夠存json。
  • ps:在MySQL 5.7版本之後支持json類型

參考資料:

我這邊作報表通常來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')

參考資料:

4.2 時間函數

昨天/近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'

參考資料:

4.3 其餘經常使用的函數

這裏我簡單整理一下我最近用過函數:

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多篇原創技術文章、海量視頻資源、精美腦圖,關注便可獲取!

轉發到朋友圈是對我最大的支持!

以爲個人文章寫得不錯,點

相關文章
相關標籤/搜索