日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

数据库高级查询与性能优化1,开窗函数与子查询

發(fā)布時(shí)間:2023/12/20 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库高级查询与性能优化1,开窗函数与子查询 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

數(shù)據(jù)庫高級(jí)查詢與性能優(yōu)化

開窗函數(shù)

對(duì)于開窗函數(shù)一般的解釋是"用于’分區(qū)’或’分組’計(jì)算的函數(shù)".聯(lián)想到聚集函數(shù),同樣是為分組而準(zhǔn)備的函數(shù)(與GROUP BY子句連用),這兩者有什么區(qū)別呢?

作為 ISO SQL 支持的開窗函數(shù)與聚集函數(shù)在使用聚合函數(shù)計(jì)算上其實(shí)差別不大, 其區(qū)別主要出現(xiàn)在兩個(gè)部分:一是在結(jié)果顯示上上面,聚集函數(shù)計(jì)算出的結(jié)果是按組別在一行輸出的,而開窗函數(shù)是在每一行上分別輸出;二是可以利用開窗,使用排名開窗函數(shù)獲取行的排名值,在OLAP系統(tǒng)和Web應(yīng)用排序上有較多的應(yīng)用.另外,兩者還在使用形式上有所不同,在編寫語句時(shí),開窗需要在SELECT子句中針對(duì)列聲明,聚集是在主句后使用GROUP BY指定目標(biāo)列.

使用開窗需要用到OVER和PARTITION BY關(guān)鍵字,基本使用方法是在SELECT中使用函數(shù)名(計(jì)算列) OVER(PARTITION BY 開窗列) AS 別名.

聚合開窗

聚合開窗與聚合函數(shù)的使用基本一致,這里使用一個(gè)實(shí)例來說明,有一張商品表,其中的存儲(chǔ)(商品名, 商品類別, 價(jià)格)等數(shù)值:

商品名商品類別價(jià)格
aX2
bX3
cX4
dY9
eY11

使用聚合函數(shù)獲取同種類別商品價(jià)格平均價(jià)格,價(jià)格之和,最高價(jià)格的語句是:

SELECT 商品類別, AVG(價(jià)格) AS 平均價(jià)格, SUM(價(jià)格) AS 價(jià)格之和, MAX(價(jià)格) AS 最高價(jià)格 FROM 商品表 GROUP BY 商品類別

結(jié)果是:

商品類別平均價(jià)格價(jià)格之和最高價(jià)格
X394
Y102011

如果使用開窗函數(shù)查詢上述數(shù)據(jù),語句應(yīng)是:

SELECT 商品類別, AVG(價(jià)格) OVER(PARTITION BY 商品類別) AS 平均價(jià)格, SUM(價(jià)格) OVER(PARTITION BY 商品類別) AS 價(jià)格之和, MAX(價(jià)格) OVER(PARTITION BY 商品類別) AS 最高價(jià)格, FROM 商品表

結(jié)果是:

商品類別平均價(jià)格價(jià)格之和最高價(jià)格
X394
X394
X394
Y102011
Y102011

上述這些冗余的結(jié)果十分令人費(fèi)解,但我們?cè)诓樵兊臅r(shí)候?qū)⑸唐访麡?biāo)識(shí)出來,就比較好理解了:

SELECT 商品名, 商品類別, AVG(價(jià)格) OVER(PARTITION BY 商品類別) AS 平均價(jià)格, SUM(價(jià)格) OVER(PARTITION BY 商品類別) AS 價(jià)格之和, MAX(價(jià)格) OVER(PARTITION BY 商品類別) AS 最高價(jià)格, FROM 商品表

結(jié)果是:

商品名商品類別平均價(jià)格價(jià)格之和最高價(jià)格
aX394
bX394
cX394
dY102011
eY102011

可以看出,使用開窗函數(shù),原來聚集函數(shù)每一組一行的數(shù)據(jù)顯示方式變成了每一條記錄顯示一行了.

排名開窗

排名開窗是開窗的重要用法,主要排名函數(shù)有四個(gè).這一部分使用一列(1, 2, 3, 1)數(shù)據(jù)來簡要說明.使用排名函數(shù),待排序的列名不是在函數(shù)的參數(shù)中指定,而是在開窗中說明.需要注意的是,開窗函數(shù)的排名方式不是在ORDER BY子句中聲明,而是在帶排名列后標(biāo)注.

RANK()

RANK()排名時(shí)會(huì)考慮到值相同的情況,也就是并列,在并列后會(huì)按照絕對(duì)位置繼續(xù)排名,換句話說,排名出來的數(shù)字不是連續(xù)的.

例如SELCET value, RANK() OVER(PARTITION BY value ASC) AS RANK排名 FROM Values的結(jié)果是

valueRANK排名
11
11
23
34

DENSE_RANK()

DENSE_RANK()排名時(shí)也會(huì)考慮到并列的情況,但其返回值是連續(xù)不間斷的.

例如SELCET value, DENSE_RANK() OVER(PARTITION BY value ASC) AS DENSE_RANK排名 FROM Values的結(jié)果是

valueDENSE_RANK排名
11
11
22
33

ROW_NUMBER()

此函數(shù)排名時(shí)不考慮并列的情況,其結(jié)果自然也是連續(xù)的.

例如SELCET value, ROW_NUMBER() OVER(PARTITION BY value ASC) AS ROW_NUMBER排名 FROM Values的結(jié)果是

valueROW_NUMBER排名
11
12
23
34

NTILE()

NTILE()函數(shù)比較特殊,是在有序分區(qū)中劃分組來排名,需要在函數(shù)參數(shù)里指明分組的數(shù)目,排名結(jié)果是組所排名的結(jié)果.

例如將前面表格分為兩組排名,使用SELCET value, NTILE(2) OVER(PARTITION BY value ASC) NTILE排名 FROM Values的結(jié)果是

valueNTILE排名
11
11
22
32

子查詢

子查詢是在SELECT語句中使用另一個(gè)SELECT語句,也被稱作內(nèi)層查詢,其外層查詢也被稱作主查詢.內(nèi)外層查詢沒有固定的先后查詢順序,根據(jù)不同的查詢語句情況(語義)有不同的查詢順序.

嵌套子查詢

嵌套子查詢,WHERE/HAVING子查詢,這種內(nèi)層查詢(子查詢)先于外層(主)進(jìn)行.基于集合的嵌套子查詢,WHERE 表達(dá)式 [NOT] IN (子查詢).比較嵌套子查詢,WHERE 表達(dá)式 比較運(yùn)算符 (使用聚合函數(shù)返回單值的子查詢).以上查詢又稱作不相關(guān)子查詢,測試子查詢.

這種查詢先進(jìn)行內(nèi)層查詢,查詢出一個(gè)集合(WHERE ... IN ...)或者查出一個(gè)數(shù)(WHERE 比較條件),然后再進(jìn)行外部查詢,外部的每一行執(zhí)行WHERE中的比較語句,檢查結(jié)果是否符合條件,若符合,則該記錄進(jìn)入最終的結(jié)果集,不符合則棄用.

例如利用子查詢方式查詢和A商品同類的商品:

SELECT 商品名, 價(jià)格, 類別 FROM 商品表 WHERE 類別 IN (SELECT 類別 FROM 商品表 WHERE 商品名 = 'A' ) AND 商品名 != 'A'

相關(guān)子查詢

相關(guān)子查詢雖然是用在WHERE/HAVING中,但執(zhí)行順序是先執(zhí)行主查詢,再主查詢中逐行進(jìn)行子查詢,根據(jù)子查詢的值決定主查詢中當(dāng)前行是否返回在結(jié)果集合中.這個(gè)子查詢的值是布爾值,形式為WHERE [NOT] EXISTS(子查詢).此種查詢也稱為存在性測試子查詢.

在這種查詢方式中,子查詢不同于嵌套子查詢只執(zhí)行一次,而是會(huì)執(zhí)行很多次的.執(zhí)行的次數(shù)根據(jù)主查詢返回的原始結(jié)果集決定.子查詢返回布爾值的邏輯是由子查詢中的WHERE決定的.可以理解為先產(chǎn)生主查詢語句中查出來的行,在主查詢完成后,逐行進(jìn)行子查詢.

例如利用相關(guān)子查詢查找單次消費(fèi)大于一萬元的客戶姓名:

SELECT DISTINCT 客戶表.姓名 FROM 客戶表 WHERE EXISTS (SELECT * FROM 銷售明細(xì)表WHERE 銷售明細(xì)表.銷售額 > 10000AND 銷售明細(xì)表.客戶編號(hào) = 客戶表.客戶編號(hào) )

替代表達(dá)式子查詢

替代表達(dá)式子查詢(SELECT子查詢)通常利用子查詢中聚合函數(shù)返回一個(gè)標(biāo)量值.其作用貌似是如同相關(guān)子查詢一樣利用主查詢的每一行進(jìn)行查找,然而事實(shí)上其查詢條件是在查詢之前就寫死再子查詢語句中的,與主查詢無關(guān),通常是只查詢某一個(gè)記錄時(shí)使用.其查詢結(jié)果將作為一呈現(xiàn)在結(jié)果中.

例如查詢客戶編號(hào)為10086的客戶名,地址和累計(jì)消費(fèi)金額:

SELECT 姓名, 地址, (SELECT SUM(銷售額) FROM 銷售明細(xì)表JOIN 客戶表 ON 客戶表.客戶編號(hào) = 銷售明細(xì)表.客戶編號(hào)WHERE 客戶表.客戶編號(hào) = 10086 ) FROM 客戶表 WHERE 客戶編號(hào) = 10086

派生表子查詢

派生表子查詢(FROM子查詢)作用類似于臨時(shí)表,在主查詢進(jìn)行前先進(jìn)性子查詢,而后主查詢以子查詢返回的表作為數(shù)據(jù)源繼續(xù)查詢,可以理解為臨時(shí)表的性能優(yōu)化方式和一種方便的用法,其形式為FROM (子查詢)或者FROM (子查詢|表) [各種連接類型] JOIN (子查詢 | 表).其性能優(yōu)化之處在于不必手動(dòng)生成臨時(shí)表,產(chǎn)生的派生表在內(nèi)存中用完即焚,避免在SQL Server調(diào)用tempdb數(shù)據(jù)庫,減少I/O帶來的性能損失.

例如查詢客戶編號(hào)為10086和10010的兩個(gè)用戶都購買了的商品有哪些:

SELECT 商品表.商品編號(hào), 商品表.商品名 FROM (SELECT * FROM 銷售明細(xì)表 WHERE 客戶編號(hào) = 10086 ) AS T1 JOIN (SELECT * FROM 銷售明細(xì)表 WHERE 客戶編號(hào) = 10010 ) AS T2 ON T1.商品編號(hào) = T2.商品編號(hào) JOIN 商品表 ON T1.商品編號(hào) = 商品表.商品編號(hào)

子查詢性能問題

需要注意的是,在WHERE子句中使用聚集函數(shù)的值不可以直接調(diào)用聚集函數(shù),需要使用子查詢的方式調(diào)用.聚合函數(shù)不能直接出現(xiàn)在WHERE子句中,需要時(shí)必須先利用子查詢獲取結(jié)果.

讀者會(huì)發(fā)現(xiàn),這一部分許多的查詢其實(shí)可以使用聯(lián)接查詢或修改WHERE條件來實(shí)現(xiàn).的確如此,但在許多復(fù)雜地查詢需求中,聯(lián)接查詢和WHERE條件并不能高效易懂地完成任務(wù),還是需要子查詢來幫忙的.在數(shù)據(jù)量大,事務(wù)多的情況下,查詢的性能表現(xiàn)十分重要,子查詢和聯(lián)接查詢等等查詢方法具體用哪一個(gè),需要結(jié)合業(yè)務(wù)邏輯,數(shù)據(jù)表結(jié)構(gòu),索引甚至是物理文件等等因素具體分析.

使用子查詢無法提高連接查詢的性能,放在存儲(chǔ)過程中也無法減少運(yùn)算量,也無法提升查詢效率.在一定程度上可以說,只要使用到了子查詢,性能一定會(huì)有折扣(聯(lián)接查詢同理).為了改善查詢性能,就需要在進(jìn)行數(shù)據(jù)庫物理設(shè)計(jì)階段,將符合3NF的關(guān)系模式進(jìn)行適度的合并,人為增加一些冗余,合理地,成本最小化地用空間換時(shí)間.

參考

[1]何玉潔, 劉乃嘉. 全國計(jì)算機(jī)等級(jí)考試三級(jí)教程-數(shù)據(jù)庫技術(shù)[M]. 高等教育出版社. 2020.
[2]Ben Forta. SQL必知必會(huì)[M]. 人民郵電出版社. 2020.
[3]史嘉權(quán). 數(shù)據(jù)庫系統(tǒng)概論[M]. 清華大學(xué)出版社. 2006.
[4]褚華, 霍邱艷. 軟件設(shè)計(jì)師教程[M]. 清華大學(xué)出版社. 2018.
[5]王珊, 陳紅. 數(shù)據(jù)庫系統(tǒng)原理教程[M]. 清華大學(xué)出版社. 1998.
[6]湯小丹, 梁紅兵, 哲鳳屏, 湯子瀛. 計(jì)算機(jī)操作系統(tǒng)[M]. 西安電子科技大學(xué)出版社. 2014.

總結(jié)

以上是生活随笔為你收集整理的数据库高级查询与性能优化1,开窗函数与子查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。