秋招沒上岸的我,頹廢了幾個月再次撿起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 的處理都是在編譯階段進行,所以它可以被當作常量表示式使用。其作用就是返回乙個物...