Oracle常用的一些sql

在SQL Server 裏的日期數據,我們經常可以用 字段 <=’2008-5-20’這樣的表達式,但在oracle卻不可以,因爲數據類型不一樣 字段是date型,’2008-5-20’是字符型,需要用to_char 或者to_number轉換成相同的類型才能進行比較。 剛開始這讓我覺得不習慣,覺得不好,不過時間長了,覺得也有不少便利之處,尤其是配合trunc啊,to_char之類的,下面簡單寫一下常用的一些對日期的操作     SELECT SYSDATE  FROM DUAL  取當前系統時間     Select trunc(sysdate) from dual 取當前日期     Select trunc(sysdate,’MM’) from dual 取當前月的第一天    Select trunc(sysdate,’YYYY’) from dual取當年的元旦     Select to_char(sysdate,’ss’) from dual取當前時間秒部分 Select to_char(sysdate,’mi’) from dual取當前時間分鐘部分 Select to_char(sysdate,’HH24’) from dual取當前時間秒小時部分 Select to_char(sysdate,’DD’) from dual取當前時間日期部分 Select to_char(sysdate,’MM’) from dual取當前時間月部分 Select to_char(sysdate,’YYYY’) from dual取當前時間年部分 Select to_char(sysdate,’w’) from dual取當前時間是一個月中的第幾周(從1日開始算) Select to_char(sysdate,’ww’) from dual取當前時間是一年中的第幾周(從1.1開始算) Select to_char(sysdate,’iw’) from dual取當前時間是一年中的第幾周(按實際日曆的) Select to_char(sysdate,’d’) from dual取當前時間是一週的第幾天,從星期天開始,週六結束 Select to_char(sysdate,'day') from dual 取當前日是星期幾,和數據庫設置的字符集有關,會輸出’Tuesday’ Select to_char(sysdate,'ddd') from dual 當前日是一年中的第幾天 Select Add_months(sysdate,12) from dual 取一年後的今天 Select sysdate-(sysdate-100) from dual 取兩個日期之間的天數 Select (sysdate-(sysdate-100))*1440 from dual 取兩個日期之間的分鐘數 Select (sysdate-(sysdate-100))*1440*60 from dual 取兩個日期之間的秒數 Select months_between(sysdate,sysdate-100) from dual 取兩個日期間隔的月份 Select last_day(sysdate) from dual 取當前月的最後天 Select next_day(sysdate,’1’) from dual 取當前日之後第一個星期天,裏面的’1’表示取星期日,如果今天正好是星期日,則會顯示下一個星期日 四、 DECODE和CASE…When…End Decode是oracle提供的一個很強大的函數,使用DECODE函數可以避免重複掃描相同記錄或重複連接相同的表,減少處理時間 Decdoe類似於if…then…else,基本語法: Decode(判斷條件, 等於條件一,輸出結果1 等於條件二,輸出結果2 … … [默認結果])   舉例:     Decode(to_char(sysdate,’d’), ’1’,’週日’ ’7’,’週六’ ’工作日’) DECODE常見用途用來輸出根據特定條件輸出不同的結果, 比如說,查看訂單時,需要統計有效 如果不用decode,需要兩條語句UNION出來纔行

SQL code
SELECT dates, SUM (qty) qty, SUM (can_qty) can_qty FROM (SELECT TRUNC (a.order_date) dates, SUM (syslast) qty, 0 can_qty FROM torderdetail a WHERE a.order_date >= TRUNC (SYSDATE-40) AND a.syslast >0 GROUP BY TRUNC (a.order_date) UNION ALL SELECT TRUNC (a.order_date) dates, 0 qty, SUM (syscancel) can_qty FROM torderdetail a WHERE a.order_date >= TRUNC (SYSDATE-40) AND a.syslast = 0 GROUP BY TRUNC (a.order_date)) GROUP BY dates

執行計劃

SQL code
Plan SELECT STATEMENT ALL_ROWS Cost: 9 Bytes: 70 Cardinality: 2 9 HASH GROUP BY Cost: 9 Bytes: 70 Cardinality: 2 8 VIEW EASYTVC_DEV. Cost: 8 Bytes: 70 Cardinality: 2 7 UNION-ALL 3 HASH GROUP BY Cost: 4 Bytes: 11 Cardinality: 1 2 TABLE ACCESS BY INDEX ROWID TABLE EASYTVC_DEV.TORDERDETAIL Cost: 3 Bytes: 11 Cardinality: 1 1 INDEX RANGE SCAN INDEX EASYTVC_DEV.IDX_TORDERDETAIL_02 Cost: 2 Cardinality: 1 6 HASH GROUP BY Cost: 4 Bytes: 14 Cardinality: 1 5 TABLE ACCESS BY INDEX ROWID TABLE EASYTVC_DEV.TORDERDETAIL Cost: 3 Bytes: 14 Cardinality: 1 4 INDEX RANGE SCAN INDEX EASYTVC_DEV.IDX_TORDERDETAIL_02 Cost: 2 Cardinality: 1

成本9 而用

SQL code
decode SELECT TRUNC (order_date) dates, SUM (DECODE (syslast, 0, 0, syslast)) qty, SUM (DECODE (syslast, 0, syscancel, 0)) can_qty FROM torderdetail a WHERE a.order_date >= TRUNC (SYSDATE - 40) GROUP BY TRUNC (order_date)

執行計劃

SQL code
Plan SELECT STATEMENT ALL_ROWS Cost: 4 Bytes: 14 Cardinality: 1 3 HASH GROUP BY Cost: 4 Bytes: 14 Cardinality: 1 2 TABLE ACCESS BY INDEX ROWID TABLE EASYTVC_DEV.TORDERDETAIL Cost: 3 Bytes: 14 Cardinality: 1 1 INDEX RANGE SCAN INDEX EASYTVC_DEV.IDX_TORDERDETAIL_02 Cost: 2 Cardinality: 1

成本只有4 效率明顯高了許多,語句也簡煉 另外個最常見的用途,就是做固定列的行列轉換 比如說有數據 Name  class score 小明  語文  80 小強  數學  90 小明  英語  89 小強  語文  70 小明  數學  95 小強  英語  85 要求出來 姓名  語文  數學  英語 小明  80    95    89 小強  70    90    85 這時候就以用decode來做

SQL code
SELECT NAME 姓名, SUM (DECODE (CLASS, '語文', score, 0)) 語文, SUM (DECODE (CLASS, '數學', score, 0)) 數學, SUM (DECODE (CLASS, '英語', score, 0)) 英語 FROM table GROUP BY NAME

CASE…When…End 和Decode差不多,語法 Case     When  條件1 符合  then 結果1     When  條件2 符合  then 結果2     Else    默認結果 End 和decode 的差別在於,decode的判斷條件只能是一個,並且只能做等於或者不等於判斷,case 可以做>、 <、>=、 <=之類的判斷,並且可以同時有多個判斷條件。 不過case語法要比decode顯得複雜,所以一般判斷條件不復雜的話,用Decode顯得簡潔點,不過case屬於標準sql,decode只有oracle提供。 五、 分析函數 Oracle提供一個強大的函數系列――分析函數,上面寫到的row_number()  over()就是其中之一,特徵就在於over() Over()裏面三類參數 Partition  by  相當於group by 後面跟相應的字段名 Order by  排序條件 Rows between 窗口函數主要用來計算一定的記錄範圍內、一定的值域內、或一段時間內的累積和及移動平均值等。之所以叫“窗口”因爲處理結果中使用了一個滑動的查詢結果集範圍。 一般常用的參數就是partition by 和order by Over() 有些時候裏面可以不寫參數,默認就是對於所有數據,例如sum(字段) over() 就是對於所有紀錄範圍求和,而有些時候order by是必須的,如row_number() over() 就是的 分析函數的優點在於,不受語句裏的group by 的限制(注,經研究,SUM,AVG等的結果還是受GROUP影響) 這裏順便說幾個關於SUM的 sum(字段) 這樣寫,除非是求所有紀錄的某字段的和,並且select只顯示sum字段,否則需要和group一起用 sum(字段) over(),也是對所有紀錄集範圍內字段求和,不需要GROUP,可以和其它字段同行顯示 比如說你可以寫這樣的

SQL code
select a.*,sum(b) over() from a

sum(字段)over(partition by 分組字段)按分組字段求和,不需要group by sum(字段1) over (order by 字段2) 按排序順序求和到當前行 比如表a 字段1  字段2 1      1 1      2 2      3 2      4 4      5 5      6 用

SQL code
select a.* sum(字段1) over (order by 字段2) c from a

出來結果 字段1  字段2  c 1      1      1 1      2      2 2      3      4 2      4      6 4      5      10 5      6      15 大家知道寫group  by時,select裏的字段除聚合函數(如sum,avg,count之類)外,其餘都要和group by 裏對應,也不能寫* 比如說上面row_number() over() 裏的例子,要求知道每天最後張訂單的所有信息,傳統的作法就需要按訂單日期每天分組,然後找最大的訂單時間,然後再和原表關聯查詢,也就是說要對同張表,做兩次掃描查詢 而用row_number() over(partition by trunc(order_date) order by order_date desc)一次可以產生分組編號,最後只要取結果爲1的就行了 常用的分析函數 Row_number() over 按分組按排序編號 Rank()      over 按分組按排序編號,有並列的,編號相同,並跳過相同數目下幾個編號 Dense_rank()  over按分組按排序編號,有並列的,編號相同,不跳號 Lag(字段名,偏移量,默認值) over 按分組排序,取當前紀錄字段的往上+偏移量條紀錄的同一字段的值,取不到的話,顯示默認值 lead(字段名,偏移量,默認值) over 基本同上,差別在於往後取紀錄 first_value(字段) over( 窗口函數) 取窗口函數範圍內的第一條紀錄,需要寫開窗函數 last_value 同上,只不過是取結果集中最後條紀錄 ratio_to_report(字段) over() 字段所佔 over結果集的百分比,像統計當天各地區銷量的佔比,傳統做法要寫兩個語句關聯,一個統計各地區的的銷量和,一個統計所有銷量和,然後再關聯計算各地方的百分比,而用這個分析函數,一條語句就夠了,如

SQL code
SELECT br_area_gb, SUM (syslast) qty, ratio_to_report (SUM (syslast)) OVER () ratio FROM torderdetail a WHERE syslast > 0 GROUP BY br_area_gb

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章