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; -- 上面我最后輸出的就是城市的數量了。