天天看點

c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

這篇主要是用舉栗子的方式來了解SQL中的視窗函數,加深大家對SQL視窗函數的了解。

c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

樣例表

這個樣例表是我為了好了解,随便設計的,不符合資料庫設計的三範式,請忽略。

(一)标準聚合函數

标準的聚合函數有avg、count、sum、max和min,接下來分别介紹這些聚合函數的視窗函數形式。

1、移動平均視窗函數

移動平均值的定義:若依次得到測定值(x1,x2,x3,...xn)時,按順序取一定個數所做的全部算數平均值。例如(x1+x2+x3)/3,(x2+x3+x4)/3,(x3+x4+x5)/3,....就是移動平均值。其中,x可以是日或者月,以上的可以成為3日移動平均,或3月移動平均,常用于股票分析中。

文法結構:
avg
           

影響行數的範圍(限定計算移動平均的範圍):

rows 
           
以v_info舉個例子吧
SELECT *,
       AVG(grade) OVER(ORDER BY stu_no ROWS BETWEEN 2 preceding AND CURRENT ROW) AS '三移動平均'
FROM v_info
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
  • 對于第一行來說,沒有前面兩行,是以值就為目前行的值
  • 對于第二行來說,前面隻有一行,是以三移動平均就為第一行和第二行的平均值
影響行數範圍的語句在标準的聚合函數中都适用。

2、計數(count)視窗函數

視窗 函數 count(*) over() 對于查詢傳回的每一行,它傳回了表中所有行的計數。

文法結構:
count
           
(1)查詢出成績在90分以上的人數
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

這個結果說明,成績大于90分的,有兩位同學。

(2)按照課程号進行分組,找出成績大于等于80分的學生人數
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

從結果上可以看出,課程号為“0001”的學生人數有2名;課程号為“0002”的學生人數有2名;課程号為“0003”的學生有3名。

3、累計求和(sum)視窗函數

文法結構:
sum
           
(1)根據學号排序,對學生的成績進行累積求和
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
(2)按照課程号分組,然後根據學号對成績進行累積求和
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
tips:一定要選擇根據學号排序,要不然得出來的是最終的累積求和結果,如下圖:
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

4、最大(max)、最小值(min)視窗函數

文法結構:
max(字段名1) over(partition by 字段名2 order by 字段名3 asc/desc) 

min(字段名1) over(partition by 字段名2 order by 字段名3 asc/desc) 
           
(1)求成績的累積最大值和累積最小值
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

按照學号進行排序,在累積最大值中,會依次往下找最大值,如果有比目前值大的,就更新,若沒有就保持目前;最小值同理。

(2)按照課程号進行分組,再求最大、最小值
SELECT *,
       MAX(grade) OVER(PARTITION BY c_no ORDER BY stu_no) AS '累積最大值',
       MIN(grade) OVER(PARTITION BY c_no ORDER BY stu_no) AS '累積最小值'
FROM v_info
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
(3)根據學生号和課程号求成績的累積最小值
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

從上圖可以看出,對于stu_no,c_no分組,後面沒有一樣的分組,是以每個stu_no,c_no都是一組,是以累積最小值就是目前的成績值。

(4)統計2019年10月1日-10月10日每天做新題的人的數量,重點在每天。
  • 這個題的重點是在每天,是以需要求出count(時間)=10的使用者ID;
  • 這個題可以使用min() over()視窗函數,先根據每個做題者和試卷号,找出每個做題者的最小日期,這裡和前面(3)的解題思路是一樣的;
  • 如果每天都做題,那麼得到的日期是不一樣的,是以count(時間)會等于10;
  • 再對這部分的使用者ID進行求和,就可以找出每天都做新題的人了。
SELECT 
           

(二)排序視窗函數

我在之前就更新過了,這裡就不重複寫了,感興趣的可以點連結,去看我之前寫的文章。

草莓女孩:SQL中常見的面試題​zhuanlan.zhihu.com

c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

(三)分組排序視窗函數

可以按照銷售額的高低、點選次數的高低,以及成績的高低為對使用者和學生進行分組,這裡的考點是:取銷售額最高的25%的使用者(将使用者分成4組,取出第一組)、取成績高的前10%的學生(将學生分成10組,取出第一組)等等。

文法結構:
ntile
           
  • ntile(n),用于将分組資料按照順序切分成n片,傳回目前切片值
  • ntile不支援rows between的用法
  • 切片如果不均勻,預設增加第一個切片的分布
(1)取出成績前25%的學生資訊
  • 第一步:按照成績的高低,将學生按照成績進行切片
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
  • 第二步:按照rank篩選出第一組,則得到最終的結果如下:
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數

(四)偏移分析視窗函數

lag() over()和lead() over()視窗函數,lag和lead分析函數可以在同一次查詢中取出同一個字段的前N行資料(lag)和後N行(lead)作為獨立的列。

在實際應用當中,若要用到取今天和昨天的某字段的內插補點時,lag和lead函數的應用就顯得尤為重要了。

适用場景:擷取使用者在某個頁面停留的起始與結束時間

文法結構:

lag
           
(1)向前推1個日期
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
  • 第一條記錄,往前推沒有,則為0,因為我設定了為0,預設為NULL;
  • 第四條記錄是在男生組裡,是以也相當于第一條記錄,是以也為0;
(2)向後推1個日期
SELECT 
           
c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
  • 在女生組裡,第三條記錄往後推1個日期是沒有的,是以為無;
  • 在男生組裡,最後一條記錄網後也是沒有的,是以也為無。
(3) 統計每天符合以下條件的使用者數:A操作之後是B操作,AB操作必須相鄰。

使用者行為表racking_log(user_id,operate_id,log_time)

解題思路:
  • 先根據使用者ID和日期,用LEAD()視窗函數向後擷取下一步的步驟;
  • AB必須相鄰,則表明目前的步驟為A,而下一個步驟為B,即A向下移的步驟是B;
  • “每天”,即根據日期進行分組。
SELECT 
           
(4)現在有某個登入表,找出連續登入7天以上的使用者(看SQL面試題一)

草莓女孩:SQL面試題(一)​zhuanlan.zhihu.com

c++ 編寫函數傳回兩個值最小值_結合執行個體來分析SQL的視窗函數
tips:視窗函數和普通函數的差別在于:普通聚合函數結果傳回的是一條,将多條記錄合成一條,而視窗函數是有幾條記錄就傳回幾條。