本文講解的知識點(diǎn)主要有 ? :公用表表達(dá)式(CTE)油宜、窗口函數(shù)希痴、SQL NULL 函數(shù)及SQL 條件判斷者甲;針對人群:對SQL一知半解,停留在增刪改查初級層面砌创,大神可以飄過虏缸。
一鲫懒、公用表表達(dá)式(Common Table Expression,CTE)
? ? ? ? CTE 可以作為臨時(shí)的結(jié)果集刽辙,可以在DML(Data Manipulation Language)語句中被多次引用窥岩,從而是語句更加簡練。
公用表達(dá)式定義 :
WITH express_name [(colum_name[,....n])]
AS
(CTE_query_definition)
(1)參數(shù)含義?
? ? ? ? express_name:公用表表達(dá)式名字宰缤;
? ? ? ?colum_name :字段名颂翼;
? ? ? ?CTE_query_definition:一個(gè)Select語句。
(2)CTE特點(diǎn)?
? ? ? ?1)在一定程度上提高SQL語句的可讀性
? ? ? ? 2)提高SQL語句執(zhí)行性能
? ? ? ? 在多表進(jìn)行 full join on (MySQL 目前不支持)慨灭,每個(gè)部分都需要使用 一個(gè)select 查詢結(jié)果集時(shí)朦乏,相應(yīng)每個(gè)部分都需要去執(zhí)行一遍,而使用WITH AS 語句 氧骤,則需執(zhí)行一次 呻疹;另外,SQL優(yōu)化器也會對WITH AS 短語做優(yōu)化语淘,連續(xù)被調(diào)用兩次以上诲宇,優(yōu)化器會自動(dòng)將WITH AS 短語的結(jié)果集存放在一個(gè)臨時(shí)表中际歼。
? ? ? ? 3)可以在一個(gè)語句中多次引用公用表表達(dá)式
? ? ? ? 4)可以定義遞歸共用表表達(dá)式
實(shí)例講解?:
獲取某APP每一天不同平臺dau數(shù)據(jù)
這個(gè)好辦惶翻,弄一個(gè)表變量不就可以了嗎
? ? ? ?一運(yùn)行報(bào)錯(cuò),查找一下PostgreSQL中并不支持declare 方式創(chuàng)建表變量鹅心,PostgreSQL只有通過函數(shù)返回record or ref Cursor吕粗。(MySQL支持)
二、窗口函數(shù)
?在將窗口函數(shù)前旭愧,先來對比一下聚合函數(shù)(min() /max() /avg()/ sum()等) 和 窗口函數(shù) :
(1)聚合函數(shù)返回的各個(gè)分組的結(jié)果颅筋,窗口函數(shù)則為每一行返回結(jié)果
? ? ? ?窗口函數(shù)計(jì)算一些行集合的數(shù)據(jù),與常規(guī)的聚集函數(shù)不同的是输枯,窗口函數(shù)不會將參與計(jì)算的行合并成一行輸出议泵,而是保留它們原來的樣子。
(2)聚合函數(shù)都支持窗口函數(shù)運(yùn)算桃熄。
(3)聚合函數(shù)對一組值執(zhí)行計(jì)算先口,并返回單個(gè)值。 除了 COUNT 以外瞳收,聚合函數(shù)都會忽略空值碉京。 聚合函數(shù)經(jīng)常與 SELECT 語句的 GROUP BY 子句一起使用。
(4)窗口函數(shù)是對一組值進(jìn)行操作螟深,不需要使用GROUP BY 子句對數(shù)據(jù)進(jìn)行分組谐宙,能夠在同一行中同時(shí)返回基礎(chǔ)行和聚合列。
實(shí)例講解 :
假設(shè)現(xiàn)在要得到某APP所有版本crash率的平均值界弧,按照通常的做法凡蜻,一定是通過聚合函數(shù)AVG來求Crash率的平均值搭综,輸出結(jié)果中包含該APP 對應(yīng)的版本、crash率及平均crash率划栓。
(1)方法 1 (初學(xué)者經(jīng)常犯的錯(cuò)誤)
出錯(cuò)原因 :Select 指定字段要么包含在聚合函數(shù)中设凹,那么包含在Group By語句后面(Group by 對Select指定字段做了限制)。
(2)方法2?
使用方法1 碰壁后 茅姜,立馬改寫成如下方式 闪朱,一看查詢結(jié)果立馬尷尬了,都按 version 和crash_rate Group by 了 钻洒,還求啥avg?
上述 兩種方法均未達(dá)到我們的目的奋姿,上一節(jié)介紹了公用表達(dá)式(CTE),那我們就先用這種方式來實(shí)現(xiàn) :
(3)CTE方式實(shí)現(xiàn)
那有沒有更加簡單的方式了 ,咱也不賣關(guān)子了 素标,竟然是將窗口函數(shù)称诗,那肯定可用窗口函數(shù)來實(shí)現(xiàn)了
(4)窗口函數(shù)實(shí)現(xiàn)
窗口函數(shù)的作用是不是很強(qiáng)大 ,使用也相當(dāng)簡單 头遭。
窗口函數(shù)使用OVER函數(shù)實(shí)現(xiàn)寓免,OVER函數(shù)分帶參和不帶參兩種。
OVER 函數(shù)定義:
OVER([PARTITION BY value_expression,..[n] ],<ORDER BY BY_Clause>?)
其中可選參數(shù)PARTITION BY用于將數(shù)據(jù)按照特定字段分組 ; ORDER BY 用于排序计维。
三袜香、SQL NULL 函數(shù)
不同的DB對應(yīng)的SQL NULL 函數(shù)均有所不同,目前SQL NULL函數(shù) 主要有以下幾種:
(1)ISNULL() —— SQL Server/MS Access
(2)NVL() —— Oracle
(3)IFNULL() —— MySQL
(4)COALESCE() —— MySQL / PostgreSQL
用法很簡單鲫惶,以COALESCE()為例蜈首,COALESCE(data,defaultValue) ,如果data為NULL欠母,那么COALESCE(data,defaultValue) 將返回 defaultValue 欢策,反之 ,返回data赏淌。
為什么數(shù)據(jù)庫中很在意對NULL的處理踩寇,這牽扯到SQL的三值邏輯 ,True(真)? 六水、False(假)俺孙、 UNKNOWN(不知道,不確定)缩擂,在數(shù)據(jù)庫中的NULL 相當(dāng)于UNKNOWN鼠冕,若對NULL值處理不當(dāng)會造成意想不到的后果。
實(shí)例:新版app在原有上報(bào)基礎(chǔ)上胯盯,新增了某些上報(bào)字段(沒有設(shè)置默認(rèn)值懈费,深坑), 后期需要對這個(gè)數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析 博脑,如 ?某版本得分 = sum( 根據(jù)各項(xiàng)指標(biāo)得分 * 權(quán)重)憎乙。
結(jié)果發(fā)現(xiàn) 低版本的得分為NULL 票罐,原因很簡單 ?某些字段只在高版本中才上報(bào),而 NULL+ 數(shù)字 = NULL 泞边。
正確做法:(1)Create Table 時(shí)该押,設(shè)置字段默認(rèn)值 ;
(2)沒有默認(rèn)值阵谚,則可利用上述的SQL NULL 函數(shù)來實(shí)現(xiàn)蚕礼。
三、SQL 條件判斷(簡要列舉)
(1) case when ?及if?
(2) insert into? ....? where not exists () 及insert overwrite
? ? ? ? ?某些數(shù)據(jù)庫不支持replace 梢什,如 PostgreSQL
引用:
(1)http://www.cnblogs.com/CareySon/archive/2011/12/12/2284740.html
(2)http://www.w3school.com.cn/sql/sql_isnull.asp
(3)https://segmentfault.com/a/1190000008332604?utm_source=tuicool&utm_medium=referral
(4)http://www.cnblogs.com/jeffwongishandsome/archive/2010/12/04/1896672.html