Oracle開窗函數 over()(轉)


copy文鏈接:http://blog.csdn.net/yjjm1990/article/details/7524167#,http://www.2cto.com/database/201402/281473.html

格式:

  可以開窗的函數(..) over(..)

  over中防止分組的條件和分組的排序,不過分組使用的不再是GROUP BY而是PARTITION BY,表示開窗

-- 建表
CREATE table tb_sc(
uName varchar2(10),
uCourse varchar2(10),
Uscore varchar2(10)
);
-- 插入數據
INSERT INTO tb_sc VALUES('張三','語文','80');
INSERT INTO tb_sc VALUES('張三','數學','95');
INSERT INTO tb_sc VALUES('李四','語文','90');
INSERT INTO tb_sc VALUES('李四','數學','70');
INSERT INTO tb_sc VALUES('王五','語文','90');
INSERT INTO tb_sc VALUES('王五','數學','90');
-- 查詢所有
SELECT * FROM tb_sc;
-- 查詢每名學生的平均分(展示姓名、平均分)
Select uName,AVG(uScore) 
FROM tb_sc
GROUP BY uName;
-- 查詢每名同學的平均分並降序排列(展示姓名、平均分)
SELECT uName,AVG(uScore) 
FROM tb_sc
GROUP BY uName
ORDER BY uName DESC;
-- 查詢平均分數高於85分的學生(展示姓名、平均分)
SELECT uName,AVG(uScore)
FROM tb_sc
GROUP BY uName
HAVING AVG(uScore)>85;
-- 查詢不為張三且平均分高於85的學生(展示姓名、平均分)
SELECT uName,AVG(uScore)
FROM tb_sc
GROUP BY uName
HAVING uName != '張三' AND AVG(uScore) >85;
-- 查詢所有學生的信息並將每個學生的各科成績降序
SELECT t.*,ROW_NUMBER() OVER(PARTITION BY t.uName ORDER BY t.uScore DESC) RM 
FROM tb_sc t;
-- 查詢每個學生考得最好的科目並展示該科目的成績
SELECT * 
FROM(
     SELECT  t.*,row_number() OVER(PARTITION BY t.uName ORDER BY t.uScore DESC) rm
     FROM tb_sc t )
WHERE rm=1;

-- 注:row_number() over(oartition by 分組字段 order by 排序字段)常用於查詢所有分組並將各個窗體進行排序

-- 在開窗函數出現之前存在着很多用SQL語句很難解決的問題,很多都要通過復雜的相關子查詢或者存儲過程來完成。為了解決這些問題,在2003年ISO、SQL標准加入了開窗看書,
-- 開窗看書的使用使得這些經典的難題可以被輕松的解決。目前在MSSQLSERVER、Oracle、DB2等主流數據庫中都提供了對開窗函數的支持,遺憾的是MYSQL暫未支持

-- 建表
CREATE TABLE T_Person(
FName VARCHAR2(20),
FCity VARCHAR2(20),
FAge INT,
FSalary INT
);

-- 插入原始數據
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Tom','BeiJing',20,3000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Tim','ChengDu',21,4000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Jim','BeiJing',22,3500);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Lily','London',21,2000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('John','NewYork',22,1000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('YaoMing','BeiJing',20,3000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Swing','London',22,2000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Guo','NewYork',20,2800);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('YuQian','BeiJing',24,8000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Ketty','London',25,8500);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Kitty','ChengDu',25,3000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Merry','BeiJing',23,3500);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Smith','ChengDu',30,3000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)  
VALUES('Bill','BeiJing',25,2000);   
INSERT INTO T_Person(FName,FCity,FAge,FSalary)   
VALUES('Jerry','NewYork',24,3300);  
-- 查看表中的內容
SELECT * 
FROM T_Person; 

-- 開窗函數簡介
-- 與聚合函數一樣,開窗函數也是對行集組進行稽核計算,但是它不像普通聚合函數那樣,每組只返回一個值,開窗函數可以每組返回多個值,
-- 因為在開窗函數所執行聚合計算的行集組是窗口。在ISO、SQL規定了這樣的函數為開窗函數,在Oracle中則被稱為分析函數,在DB2中則被稱
-- 為OLAP函數

--計算人員的總數
SELECT COUNT(*) FROM T_Person;
-- 查詢每個工資小於5000員的員工信息(城市以及年齡),並且在每行中都顯示所有工資小於5000元的員工的個數
SELECT FCity,FAge,COUNT(*)
FROM T_Person
WHERE FSalary <5000
GROUP BY FCity,FAge;
-- 上面得到的count的值有問題,因為count統計的是分組中的總數,而分組的條件其實被改變了
SELECT FCity,FAge,(SELECT COUNT(*) FROM T_Person WHERE FSalary <5000) 
FROM T_Person
WHERE FSalary <5000;
-- 上面可以解決問題,有點惡心就是,我們使用開窗函數
SELECT FCity,FAge,COUNT(*) OVER()
FROM T_Person
WHERE FSalary <5000;
-- 可以看到與聚合函數不同的是,開窗函數在聚合函數后增加了一個OEVR關鍵字。
-- 開窗函數的調用格式為: 聚合函數(...) OVER(選項)
-- OVER關鍵字把函數當成開窗函數而不是聚合函數。SQL標准允許將所有聚合函數用做開窗函數,使用OVER關鍵字來區分這兩種用法
-- OVER中的選項使用PARTITION BY 替代GROUP BY,也可以含有ORDER BY子句.也就是說開窗函數中是分組的條件和依據,不過GROUP BY 使用PARTITION BY替代。
SELECT FCity,FAge,COUNT(*) OVER(PARTITION BY FCity)
FROM T_Person
WHERE FSalary <5000;
-- 上面我最后輸出的就是城市的數量了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM