1. 程式人生 > 資料庫 >PostgreSQL資料庫中視窗函式的語法與使用

PostgreSQL資料庫中視窗函式的語法與使用

什麼是視窗函式?

一個視窗函式在一系列與當前行有某種關聯的錶行上執行一種計算。這與一個聚集函式所完成的計算有可比之處。但是視窗函式並不會使多行被聚整合一個單獨的輸出行,這與通常的非視窗聚集函式不同。取而代之,行保留它們獨立的標識。在這些現象背後,視窗函式可以訪問的不僅僅是查詢結果的當前行。

  • 可以訪問與當前記錄相關的多行記錄;
  • 不會使多行聚整合一行, 與聚集函式的區別;

視窗函式語法

視窗函式跟隨一個 OVER 子句, OVER 子句決定究竟查詢中的哪些行被分離出來由視窗函式處理。

可以包含分割槽 (PARTITION BY) 和排序 (ORDER BY) 指令, 這二者都是可選的。

window_func() OVER([PARTITION BY field] [ORDER BY field])

如果沒有指定 PARTITION BY 和 ORDER BY 指令, 則等同於聚合函式, 對全部資料進行計算。

PARTITION BY 子句將查詢的行分組成為分割槽, 視窗函式會獨立地處理它們。PARTITION BY 工作起來類似於一個查詢級別的 GROUP BY 子句, 不過它的表示式總是隻是表示式並且不能是輸出列的名稱或編號。 如果沒有 PARTITION BY, 該查詢產生的所有行被當作一個單一分割槽來處理。

ORDER BY 子句決定被視窗函式處理的一個分割槽中的行的順序。 它工作起來類似於一個查詢級別的 ORDER BY 子句, 但是同樣不能使用輸出列的名稱或編號。 如果沒有 ORDER BY, 行將被以未指定的順序被處理。

PostgreSQL 中的聚合函式也可以作為視窗函式來使用

除了這些內建的視窗函式外,任何內建的或使用者定義的通用或統計聚集(也就是有序集或假想集聚集除外)都可以作為視窗函式。僅當呼叫跟著OVER子句時,聚集函式才會作為視窗函式;否則它們作為非視窗的聚集併為剩餘的集合返回單行。

視窗函式示例

員工工資 (emp_salary) 表結構如下:

SELECT emp_no,dep_name,salary
FROM public.emp_salary
order by dep_name,emp_no;

emp_id dep_name salary
7 develop 4200
8 develop 6000
9 develop 4500
10 develop 5200
11 develop 5200
2 personnel 3900
5 personnel 3500
1 sales 5000
3 sales 4800
4 sales 4800

如果要將每位員工與其部門的平均工資進行對比, 需要這樣的結果:

emp_id dep_name salary avg
7 develop 4200 5020
8 develop 6000 5020
9 develop 4500 5020
10 develop 5200 5020
11 develop 5200 5020
2 personnel 3900 3700
5 personnel 3500 3700
1 sales 5000 4866.66666666667
3 sales 4800 4866.66666666667
4 sales 4800 4866.66666666667

如果不用視窗函式來查詢, 則比較複雜, 當然也能做到, 語句如下:

SELECT e0.emp_no,e0.dep_name,e0.salary,e2.avg_salary
FROM public.emp_salary e0
join (
 select e1.dep_name,avg(e1.salary) as avg_salary
 from public.emp_salary e1
 group by e1.dep_name
) e2 on e2.dep_name = e0.dep_name
order by e0.dep_name,e0.emp_no;

如果使用視窗函式進行查詢, 則很容易做到, sql 語句如下:

SELECT emp_no,salary,avg(salary) over(partition by dep_name)
FROM public.emp_salary
order by dep_name,emp_no;

但是如果要查詢隨著員工的增加, 各部門平均工資的變化, 如下表所示的結果, 不用視窗函式查詢的話就很難做到了。

emp_id dep_name salary avg
7 develop 4200 4200
8 develop 6000 5100
9 develop 4500 4900
10 develop 5200 4975
11 develop 5200 5020
2 personnel 3900 3900
5 personnel 3500 3700
1 sales 5000 5000
3 sales 4800 4900
4 sales 4800 4866.66666666667

如果使用視窗函式, 依然可以輕鬆完成, 語句如下:

SELECT emp_no,avg(salary) over(partition by dep_name order by emp_no)
FROM public.emp_salary
order by dep_name,emp_no;

可見, 視窗函式在需要對查詢結果中的相關行進行計算時有很大的優勢。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支援。