GROUP BY、PARTITION BY,分組取前幾條,分組完整記錄,排名、排序
(一) 《SQL進階教程》學習記錄--CASE
(二) 《SQL進階教程》學習記錄--GROUP BY、PARTITION BY
GROUP BY <列名1>, <列名2>, <列名3>,根據列分組,通常配合聚合函數用于一些統計的需求。
例1:統計成績

下面簡豐富一下表結構改名fraction,插入兩期成績
例2:取兩期成績相同
配合HAVING,找兩期成績一樣的同學、科目。
通常例1無法滿我們的需求,還要知道最高分是誰,哪一期成績等,包括前三、前十等需求
例3:取各科目最高、前三
看到結果條數好像不太對,是因為同分的也查了出來,這是其一,還有另一個問題,寫起where條件也麻煩,比如隻查第一期成績。
實際業務、表結構都要比例子要複雜的多,sql語句會變得無比冗長,而且子查詢還有性能問題。
GROUP BY 和 PARTITION BY 都可以根據指定的列為表分組,差別在于 GROUP BY 在分組之後會把每個分組聚合成一行資料。partition by 通常會和 ROW_NUMBER()、RANK() 等視窗函數配合使用。
例4:各種分組、排名、排序
三個視窗函數,選擇合适的完成需求,分組、排序、where條件寫起來友善簡單,邏輯清晰。rank,dense_rank的差別是一個跳号,一個不跳号。
直接使用 || 合并, 例如 SELECT username || subject || '成績 : ' || fraction as info FROM study
或者函數concat_ws,例如 SELECT concat_ws('',username,subject,'成績 : ',fraction) as info FROM study where fraction=100
效果相同
比如測試插入表資料,簡單的循環需求,可以用函數generate_series傳回一個數組,不用存儲過程和遊标。
例如:INSERT INTO study_test SELECT '體測', '張三', round(random()::numeric,2) * 100 FROM generate_series(1,10)
測試簽名