2021 02 05 視窗函式及其應用

2021-10-19 05:19:29 字數 4415 閱讀 7688

秋招沒上岸的我,頹廢了幾個月再次撿起sql,作為記錄和自我監督,從今天開始要積極的總結各種刷題面經,也歡迎在極小的概率裡與我的菜雞分析相遇的,一起朝著資料分析方向努力的朋友們,大佬們討論指點!

———————————————————————————— 正題分界線 ——————————————————————————

因為在多個面經中看到大佬們被多次以手寫or口述等多種方式問及的,簡短卻功能強大,優雅的視窗函式,所以我從這裡結合牛客上相關的sql開始撿回sql記憶。

視窗函式有哪些以及用法

詳細指路知乎上大神的通俗易懂的解釋:

例題整理和解析(由易到難)

sql23-對所有員工的當前薪水按照salary進行按照1-n的排名

select emp_no, salary, 

dense_rank(

)over

(order

by salary desc

)as t_rank

/*這裡需要注意一下 partition by 在這題無了,

是因為如果按照emp_no分組的話,那麼每個員工內部拿到的工資進行排序,

而這裡的工資表乙個員工只有一條記錄,如果partition by emp_no,

則每個員工的排序都是1. */

from salaries

where to_date =

'9999-01-01'

/*這個日期似乎大部分題裡都有,應該是想表示是當前員工*/

order

by t_rank, emp_no asc

;/*相同salary並列且按照emp_no公升序排列*/

sql60-統計salary的累計和running_total

方法一:使用視窗函式

select emp_no, salary,

sum(salary)

over

(order

by emp_no asc

)as running_total

/*別忘了,聚合函式也可以用作視窗函式!而且這種累計計算的題非常好用!*/

from salaries

where to_date =

'9999-01-01'

;/*又又出現了*/

方法二:使用關聯子查詢

關聯子查詢我在看《learning sql》的時候就覺得非常迷茫,為何要設計乙個這樣的邏輯出來?但不得不說,關聯子查詢挺方便的,想要搞懂,看這篇——>

select s1. emp_no, s1.salaries,

(select

sum(s2.salaries)

from salaries as s2

where s2.emp_no <= s1.emp_no

/*s1是作為主表查詢,確定s1.emp_no後,

將s2中對應的位於s1.emp_no上方的salary相加*/

and to_date =

'9999-01-01'

)as running_total

from salaries as s1

where to_date =

'9999-01-01'

order

by emp_no asc

;

為了加深對關聯子查詢邏輯的理解,這道題值得根據其執行邏輯好好說說。(看了指路的解析之後才發現原來關聯子查詢和正常的sql執行順序不同!)

1) 首先執行主查詢

select s1. emp_no, s1.salaries

from salaries as s1

2) 得到s1表中的第乙個emp_no, 放入子查詢中執行,得到乙個sum()的值

select

sum(s2.salaries)

from salaries as s2

where s2.emp_no <= s1.emp_no

and to_date =

'9999-01-01'

3)返回主查詢,得到第乙個結果。後續以此類推

sql61-對於employees表中,給出奇數行的first_name

select e.first_name

from employees as e

inner

join

(select first_name,

row_number(

)over

(order

by first_name asc

)as rank

from employees)

as tb

on e.first_name = tb.first_name

where tb.rank%2=

1;

這道題可以幫助同時複習三個知識點:

1)視窗函式的row_number()函式

2)where的原理:是在資料表中的字段中進行篩選,這也是這裡的「where tb.rank%2 = 1」不能放入tb括號中的原因。

3)篩選奇數如何操作:欄位%2=1, %是模除,1為除2後的餘數

sql63-刷題通過的題目排名

方法一:使用視窗函式

select id, number, 

dense_rank(

)over

(order

by number desc

)as t_rank

from passing_number

order

by t_rank, id asc

;

select

p1.id,

p1.number,

count

(distinct p2.number )

as rank

from passing_number p1, passing_number p2

where p1.number <= p2.number

group

by p1.id

order

by rank asc

, p1.id asc

;

有時候越是覺得理所應當的容易事兒卻越缺乏對含義的透徹理解。

不占用下乙個名次的排名的含義:比我大的人有多少(這是排名的含義),並列的只算一次(這是不占用下一名次的含義)

——例如,比我大的人有3個,那麼我就是第四,這是排名;

——例如,比我大的人有5個,並列的共4個人,那麼有1人沒並列,並列的4人算2人,比我大的有3人,我依然是第四,這是不占用下乙個名次;

這題可以把一張表複製出來,對比兩表,表一中的number比表二中的number小或者相等的number,number相同的情況下只算乙個,共有幾個?

視窗函式固然簡單還用,但sql題我覺得方法通常不止一種,還是要多想邏輯。

sql76-考試分數(五)

select id, job, score, dr as t_rank

from

(select id, job, score,

row_number(

)over

(partition

by job order

by score desc

)as dr,

row_number(

)over

(partition

by job order

by score asc

)as ar,

count

(id)

over

(partition

by job)

as num

from grade)

as tb

where

(num%2=

1and dr = ar)

or(num%2=

0and abs(dr-ar)=1

)order

by id asc

;

考察的知識點:

1)專用視窗函式和聚合函式作視窗函式的應用

2)中位數的邏輯

這道題最要緊的是「中位數」,無知的我一開始以為應該有聚合函式求中位數吧(實際上我從來沒求過中位數…),結果…所以說,還是要透徹理解中位數是怎麼來的。

中位數大家都懂,從小到大排序後,處在數列中最中間的數。

如果數列有奇數個,則中位數是從頭數和從尾數都是同乙個數,例如12345,3永遠是第三個;

如果數列有偶數個,則中位數會有兩個,需要求最中間兩個數的平均值,例如1234,中位數為(2+3)/2 = 2.5

但排名是無小數的,因此數列為偶數個時,中位數只好兩個都取,兩個又是緊挨著的,只相差1的連續數。

2021 02 05 函式的高階 函式的返回值

1 引數的補充 1.1 引數記憶體位址相關 如果想要知道某個值在記憶體中的位址 v1 data addr id v1 print addr 函式執行傳參的時候,傳遞的是記憶體位址 def func data print data,id data v1 wahaha func v1 傳輸的v1和def...

子視窗及其相關

建立子視窗 btnlook 定義了乙個叫做button的結構,它包括了按鈕視窗樣式和描述性字串,它們對應於10個按鈕型態,所有按鈕視窗樣式都以字母 bs 開頭,它表示 按鈕樣式 10個按鈕子視窗是在wndproc中處理wm create訊息的過程中使用乙個for迴圈建立的。createwindow呼...

sizeof函式的使用及其在DSP中的應用

3 dsp中sizeof的用法 4 sizeof的用法問題 5 其他相關問題 sizeof是c c 中的乙個操作符 operator 簡單的說其作用就是返回乙個物件或者型別所佔的記憶體位元組數。c語言中,對 sizeof 的處理都是在編譯階段進行,所以它可以被當作常量表示式使用。其作用就是返回乙個物...