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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【学习笔记】分析函数(开窗函数)

發布時間:2025/3/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【学习笔记】分析函数(开窗函数) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

分析函數

這里的分析函數也就是我們常說的開窗函數,通常有兩類:

一類是聚合開窗函數(SUM、AVG、MAX、MIN、COUNT等),

一類是排序開窗函數(ROW_NUMBER、DENSE_RANK、RANK等)。

本文主要內容轉自《高效使用Greenplum》一書。

分析函數是Greenplum數據庫管理系統自帶函數中的一種專門解決具有復雜統計需求的函數,它可以對數據分組,然后基于組中數據進行分析統計,最后在每組數據集的每一行返回這個統計值。

分析函數不同于分組統計(Group By),分組統計只能按照分組字段返回一個固定的統計值,不能在原來的數據行上附帶這個統計值,而分析函數正式專門解決這類統計需求所開發出來的函數。分析函數已經逐步稱為SQL標準的一部分,有越來越多的數據庫系統開始支持分析函數。

開窗函數和聚合函數的區別如下:

  • SQL 標準允許將所有聚合函數用作開窗函數,用OVER 關鍵字區分開窗函數和聚合函數。
  • 聚合函數每組只返回一個值,開窗函數每組可返回多個值。

分析函數的語法結構如下:

SELECT table.column,

analysis_function() OVER ( [PARTITION BY 字符] [ORDER BY 字段 [rows]] ) as 統計值

FROM table

其中:

analysis_function():指定分析函數名稱,常用的分析函數有sum、max、first_value、last_value、lag、lead、rank、desn_rank、row_number等。

OVER():開窗函數名,PARTITION BY指定進行數據分組的字段,ORDER BY指定進行排序的字段,ROWS指定數據窗口(即指定分析函數要操作的行數),語法形式為OVER(PARTITION BY xxx ORDER BY yyy ROWS BETWEEN zzz)。

這里的ROWS有多個范圍值(一般情況下會省略),具體如下:

  • unbounded preceding:無限/不限定往前的范圍;
  • n preceding:往前統計n行;
  • unbounded following:無限/不限定往后的范圍;
  • n following:往后統計n行;
  • current row:當前行;
  • 案例:下圖是員工表和部門表數據內連接后的結果集。

    select b.dept_id,b.dept_name,t.emp_id,t.emp_name,t.age,t.salary

    from emp t,dept b

    where t.dept_id = b.dept_id

    dept_id

    dept_name

    emp_id

    emp_name

    age

    salary

    1100

    銷售部

    3

    Jack

    40

    15000

    1100

    銷售部

    4

    Michael

    36

    9800

    1200

    研發部

    2

    Alen

    29

    13500

    1200

    研發部

    5

    Lily

    36

    12500

    1110

    銷售一部

    6

    David

    30

    7900

    1120

    銷售二部

    7

    Timmy

    26

    8500

    1000

    總裁辦

    1

    Paul

    45

    36000

    案例1:利用min(),max()分析函數分別取出不同部門不同員工工資的最高值和最低值,附帶在原始數據上。

    select b.dept_id,b.dept_name,t.emp_id,t.emp_name,t.age,t.salary

    -- 獲取組中工資最高值

    max(t.salary) OVER(PARTITION BY t.dept_id) AS salary_max,

    -- 獲取組中工資最低值

    min(t.salary) OVER(PARTITION BY t.dept_id) AS salary_min,

    -- 分組窗口的第一個值(指定窗口為組中第一行到末尾行)

    first_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS salary_first,

    -- 分組窗口的最后一個值(指定窗口為組中第一行到末尾行)

    last_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS salary_last,

    -- 分組窗口的第一個值(不指定窗口)

    first_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC) AS salary_first_1,

    -- 分組窗口的最后一個值(指定窗口才可以取到最低值,否則只能取到當前行)

    last_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS salary_last_1

    from emp t,dept b

    where t.dept_id = b.dept_id

    order by t.dept_id,t.emp_id

    根據查詢結果可以看出如下信息:

    min()和max()分析函數直接獲取組中最小值和最大值;

    first_value()和last_value()返回窗口的第一行和最后一行數據,因為我們通過工資字段對分組內的數據進行了降序排列,所以也可以達到在一定的窗口內獲取最大值和最小值的功能;

    排序不指定窗口時,就按照組內的第一行到當前行作為窗口,然后取出窗口的第一行和最后一行;

    窗口子語句當中的第一行是UNBOUNDED PRECEDING,當前行是CURRENT ROW,最后一行是UNBOUNDED FOLLOWING,正是利用窗口范圍是第一行到最后一行,得到同一部門內的最高工資和最低工資。

    注意:ROWS的默認值是:BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。

    案例2:利用rank()、dense_rank()、row_number()函數對員工的年齡進行排序,比較三個不同關鍵字的差異。

    select t.emp_id,t.emp.name,t.age,

    row_number() OVER(ORDER BY t.age) AS “row_number排名”,

    rank() OVER(ORDER BY t.age) AS “rank排名”,

    dense_rank() OVER(ORDER BY t.age) AS “dense_rank排名”

    from emp t

    order by t.age

    根據查詢結果可以看出如下信息:

    emp_id

    emp_name

    age

    row_number

    rank

    dense_rank

    7

    Timmy

    26

    1

    1

    1

    2

    Alen

    29

    2

    2

    2

    6

    David

    30

    3

    3

    3

    4

    Michael

    36

    4

    4

    4

    5

    Lily

    36

    5

    4

    4

    3

    Jack

    40

    6

    6

    5

    1

    Paul

    45

    7

    7

    6

    row_number()函數排名返回唯一值,當遇到相同的數據時,排名按照記錄集中的記錄順序依次遞增;

    rank()函數返回唯一值,當遇到相同的數據時,所有相同的數據的排名是一樣的,同時會在最后一條相同記錄和下一條不同記錄的排名之間空出排名;

    dense_rank()函數返回唯一值,當遇到相同的數據時,所有相同數據的排名是一樣的,同時在最后一條相同記錄和下一條不同記錄的排名之間不空出排名。

    案例3:利用開窗函數對員工工資進行不同條件的匯總,以便對比ORDER BY和PARTITION BY的作用。

    select t.emp_id,t.emp_name,t.age,t.salary,

    sum(t.salary) OVER() AS “全局匯總”,

    sum(t.salary) OVER(ORDER BY t.emp_id) AS “逐行累加”,

    sum(t.salary) OVER(PARTITION BY t.dept_id) AS “分組匯總”,

    sum(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.emp_id) AS “分組逐行匯總”

    from emp t

    order by t.emp_id

    根據查詢結果可以看出如下信息:

    OVER()默認是全局匯總,即所有可以查到的行數指標合集,可用于計算占比;

    OVER+ORDER BY用于根據條件逐行相加匯總,可用于計算類似于“工資占前80%的員工明細”之類的需求;

    OVER+PARTITION BY用于分組匯總,可以計算分組的合計、分組的占比、分組的最大值和最小值等;

    OVER+PARTITION BY+ORDER BY用于分組逐行匯總,可用于計算分組的排名,可以滿足例如“取每一個組的前五名”之類的需求;

    案例4:查詢部門總工資大于所有部門平均總工資的部門員工信息及部門平均工資、公司平均工資。

    select * from (

    select emp_id,emp_name,dept_id,salary,

    avg(salary) OVER(PARTITION BY dept_id) as dept_avg_salary,

    avg(salary) OVER() as comp_avg_salary

    from emp) t

    where t.dept_avg_salary > t.comp_avg_salary;

    總結

    以上是生活随笔為你收集整理的【学习笔记】分析函数(开窗函数)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。