Oracle SQL依然無(wú)可替代--《Mastering Oracle SQL》(轉(zhuǎn)載)
Posted on 2005-12-06 22:04 Terry的Blog 閱讀(872) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): oracle 、轉(zhuǎn)載選擇自 calvinxiu 的 Blog http://dev.csdn.net/user/calvinxiu
天寒地凍,呆在家里又讀完了《Mastering Oracle SQL》2nd,發(fā)現(xiàn)Oracle的功能還是很強(qiáng)悍,光函數(shù)就有兩百個(gè),HSQL是很難比擬的。接下來(lái)的硬骨頭,看來(lái)要么冒險(xiǎn)用Hibernate3.0 的SQL Mapping功能,要么就自己跑JDBC組裝VO了。
1.報(bào)表合計(jì)專用的Rollup函數(shù)
銷(xiāo)售報(bào)表
廣州 1月 2000元
廣州 2月 2500元
廣州 4500元
深圳 1月 1000元
深圳 2月 2000元
深圳 3000元
所有地區(qū) 7500元
銷(xiāo)售報(bào)表
廣州 1月 2000元
廣州 2月 2500元
廣州 4500元
深圳 1月 1000元
深圳 2月 2000元
深圳 3000元
所有地區(qū) 7500元
以往的查詢SQL:
Select area,month,sum(money) from SaleOrder group by area,month
然后廣州,深圳的合計(jì)和所有地區(qū)合計(jì)都需要在程序里自行累計(jì)
1.其實(shí)可以使用如下SQL: Select area,month,sum(total_sale) from SaleOrder group by rollup(area,month)就能產(chǎn)生和報(bào)表一模一樣的紀(jì)錄
2.如果year不想累加,可以寫(xiě)成 Select year,month,area,sum(total_sale) from SaleOrder group by year, rollup(month,area) 另外Oracle 9i還支持如下語(yǔ)法: Select year,month,area,sum(total_sale) from SaleOrder group by rollup((year,month),area)
3.如果使用Cube(area,month)而不是RollUp(area,month),除了獲得每個(gè)地區(qū)的合計(jì)之外,還將獲得每個(gè)月份的合計(jì),在報(bào)表最后顯示。
4.Grouping讓合計(jì)列更好讀
RollUp在顯示廣州合計(jì)時(shí),月份列為NULL,但更好的做法應(yīng)該是顯示為"所有月份"
Grouping就是用來(lái)判斷當(dāng)前Column是否是一個(gè)合計(jì)列,1為yes,然后用Decode把它轉(zhuǎn)為"所有月份" Select Decode(Grouping(area),1,'所有地區(qū)',area) area,
Decode(Grouping(month),1,'所有月份',month),
sum(money)
From SaleOrder
Group by RollUp(area,month);
RollUp在顯示廣州合計(jì)時(shí),月份列為NULL,但更好的做法應(yīng)該是顯示為"所有月份"
Grouping就是用來(lái)判斷當(dāng)前Column是否是一個(gè)合計(jì)列,1為yes,然后用Decode把它轉(zhuǎn)為"所有月份" Select Decode(Grouping(area),1,'所有地區(qū)',area) area,
Decode(Grouping(month),1,'所有月份',month),
sum(money)
From SaleOrder
Group by RollUp(area,month);
2.對(duì)多級(jí)層次查詢的start with.....connect by
比如人員組織,產(chǎn)品類(lèi)別,Oracle提供了很經(jīng)典的方法
比如人員組織,產(chǎn)品類(lèi)別,Oracle提供了很經(jīng)典的方法
SELECT LEVEL, name, emp_id,manager_emp_id
FROM employee
START WITH manager_emp_id is null
CONNECT BY PRIOR emp_id = manager_emp_id;
FROM employee
START WITH manager_emp_id is null
CONNECT BY PRIOR emp_id = manager_emp_id;
上面的語(yǔ)句demo了全部的應(yīng)用,start with指明從哪里開(kāi)始遍歷樹(shù),如果從根開(kāi)始,那么它的manager應(yīng)該是Null,如果從某個(gè)職員開(kāi)始,可以寫(xiě)成emp_id='11'
CONNECT BY 就是指明父子關(guān)系,注意PRIOR位置
另外還有一個(gè)LEVEL列,顯示節(jié)點(diǎn)的層次
CONNECT BY 就是指明父子關(guān)系,注意PRIOR位置
另外還有一個(gè)LEVEL列,顯示節(jié)點(diǎn)的層次
3.更多報(bào)表/分析決策功能
3.1 分析功能的基本結(jié)構(gòu)
分析功能() over( partion子句,order by子句,窗口子句)
概念上很難講清楚,還是用例子說(shuō)話比較好.
3.1 分析功能的基本結(jié)構(gòu)
分析功能() over( partion子句,order by子句,窗口子句)
概念上很難講清楚,還是用例子說(shuō)話比較好.
3.2 Row_Number 和 Rank, DENSE_Rank
用于選出Top 3 sales這樣的報(bào)表
當(dāng)兩個(gè)業(yè)務(wù)員可能有相同業(yè)績(jī)時(shí),就要使用Rank和Dense_Rank
比如
金額 RowNum Rank Dense_Rank
張三 4000元 1 1 1
李四 3000元 2 2 2
錢(qián)五 2000元 3 3 3
孫六 2000元 4 3 3
丁七 1000元 5 5 4
用于選出Top 3 sales這樣的報(bào)表
當(dāng)兩個(gè)業(yè)務(wù)員可能有相同業(yè)績(jī)時(shí),就要使用Rank和Dense_Rank
比如
金額 RowNum Rank Dense_Rank
張三 4000元 1 1 1
李四 3000元 2 2 2
錢(qián)五 2000元 3 3 3
孫六 2000元 4 3 3
丁七 1000元 5 5 4
這時(shí),應(yīng)該把并列第三的錢(qián)五和孫六都選進(jìn)去,所以用Ranking功能比RowNumber保險(xiǎn).至于Desnse還是Ranking就看具體情況了。
SELECT salesperson_id, SUM(tot_sales) sp_sales,
RANK( ) OVER (ORDER BY SUM(tot_sales) DESC) sales_rank
FROM orders
GROUP BY salesperson_id
RANK( ) OVER (ORDER BY SUM(tot_sales) DESC) sales_rank
FROM orders
GROUP BY salesperson_id
3.3 NTILE 把紀(jì)錄平分成甲乙丙丁四等
比如我想取得前25%的紀(jì)錄,或者把25%的紀(jì)錄當(dāng)作同一個(gè)level平等對(duì)待,把另25%當(dāng)作另一個(gè)Level平等對(duì)待
比如我想取得前25%的紀(jì)錄,或者把25%的紀(jì)錄當(dāng)作同一個(gè)level平等對(duì)待,把另25%當(dāng)作另一個(gè)Level平等對(duì)待
SELECT cust_nbr, SUM(tot_sales) cust_sales,
NTILE(4) OVER (ORDER BY SUM(tot_sales) DESC) sales_quartile
FROM orders
GROUP BY cust_nbr
ORDER BY 3,2 DESC;NTITLE(4)把紀(jì)錄以 SUM(tot_sales)排序分成4份.
NTILE(4) OVER (ORDER BY SUM(tot_sales) DESC) sales_quartile
FROM orders
GROUP BY cust_nbr
ORDER BY 3,2 DESC;NTITLE(4)把紀(jì)錄以 SUM(tot_sales)排序分成4份.
3.4 輔助分析列和Windows Function
報(bào)表除了基本事實(shí)數(shù)據(jù)外,總希望旁邊多些全年總銷(xiāo)量,到目前為止的累計(jì)銷(xiāo)量,前后三個(gè)月的平均銷(xiāo)量這樣的列來(lái)參考.
這種前后三個(gè)月的平均和到目前為止的累計(jì)銷(xiāo)量就叫windows function, 見(jiàn)下例 SELECT month, SUM(tot_sales) monthly_sales,
SUM(SUM(tot_sales)) OVER (ORDER BY month
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_preceeding
FROM orders
GROUP BY month
ORDER BY month;
SELECT month, SUM(tot_sales) monthly_sales,
AVG(SUM(tot_sales)) OVER (ORDER BY month
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) rolling_avg
FROM orders
GROUP BY month
ORDER BY month;
報(bào)表除了基本事實(shí)數(shù)據(jù)外,總希望旁邊多些全年總銷(xiāo)量,到目前為止的累計(jì)銷(xiāo)量,前后三個(gè)月的平均銷(xiāo)量這樣的列來(lái)參考.
這種前后三個(gè)月的平均和到目前為止的累計(jì)銷(xiāo)量就叫windows function, 見(jiàn)下例 SELECT month, SUM(tot_sales) monthly_sales,
SUM(SUM(tot_sales)) OVER (ORDER BY month
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_preceeding
FROM orders
GROUP BY month
ORDER BY month;
SELECT month, SUM(tot_sales) monthly_sales,
AVG(SUM(tot_sales)) OVER (ORDER BY month
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) rolling_avg
FROM orders
GROUP BY month
ORDER BY month;
Windows Function的關(guān)鍵就是Windows子句的幾個(gè)取值
1 PRECEDING 之前的一條記錄
1 FOLLOWING 之后的一條記錄
UNBOUNDED PRECEDING 之前的所有記錄
CURRENT ROW 當(dāng)前紀(jì)錄
1 PRECEDING 之前的一條記錄
1 FOLLOWING 之后的一條記錄
UNBOUNDED PRECEDING 之前的所有記錄
CURRENT ROW 當(dāng)前紀(jì)錄
4.SubQuery總結(jié)
SubQuery天天用了,理論上總結(jié)一下.SubQuery 分三種
1.Noncorrelated 子查詢 最普通的樣式.
2.Correlated Subqueries 把父查詢的列拉到子查詢里面去,頭一回cyt教我的時(shí)候理解了半天.
3.Inline View 也被當(dāng)成最普通的樣式用了.
SubQuery天天用了,理論上總結(jié)一下.SubQuery 分三種
1.Noncorrelated 子查詢 最普通的樣式.
2.Correlated Subqueries 把父查詢的列拉到子查詢里面去,頭一回cyt教我的時(shí)候理解了半天.
3.Inline View 也被當(dāng)成最普通的樣式用了.
然后Noncorrelated 子查詢又有三種情況
1.返回一行一列 where price < (select max(price) from goods )
2.返回多行一列 where price>= ALL (select price from goods where type=2)
or where NOT price< ANY(select price from goods where type=2)
最常用的IN其實(shí)就是=ANY()
3.返回多行多列 一次返回多列當(dāng)然就節(jié)省了查詢時(shí)間 UPDATE monthly_orders
SET (tot_orders, max_order_amt) =
(SELECT COUNT(*), MAX(sale_price)
FROM cust_order)
DELETE FROM line_item
WHERE (order_nbr, part_nbr) IN
(SELECT order_nbr, part_nbr FROM cust_order c)
1.返回一行一列 where price < (select max(price) from goods )
2.返回多行一列 where price>= ALL (select price from goods where type=2)
or where NOT price< ANY(select price from goods where type=2)
最常用的IN其實(shí)就是=ANY()
3.返回多行多列 一次返回多列當(dāng)然就節(jié)省了查詢時(shí)間 UPDATE monthly_orders
SET (tot_orders, max_order_amt) =
(SELECT COUNT(*), MAX(sale_price)
FROM cust_order)
DELETE FROM line_item
WHERE (order_nbr, part_nbr) IN
(SELECT order_nbr, part_nbr FROM cust_order c)