[轉]decode函式和行列互換
http://tech.it168.com/a2010/0412/872/000000872348.shtml
Decode函式的語法結構如下:
decode (expression, search_1, result_1)
decode (expression, search_1, result_1, search_2, result_2)
decode (expression, search_1, result_1, search_2, result_2, ....,
search_n, result_n)
decode (expression, search_1, result_1, default)
decode (expression, search_1, result_1, search_2, result_2, default)
decode (expression, search_1, result_1, search_2, result_2, ....,
search_n, result_n, default)
作用:和case表示式實現的功能一樣,以第1 個引數為關鍵欄位,如果等於search,則結果為對應的result,最後匹配不到的結果為default。如果沒有寫default,返回null。 為了格式一致,建議匹配不到不返回結果時,寫null。如果第一個返回結果為char 或null,oracle自動轉型為varchar2,如下面例子
SELECT product_id,
DECODE (warehouse_id, 1, ’Southlake’,
2, ’San Francisco’,
3, ’New Jersey’,
4, ’Seattle’,
’Non-domestic’)
"Location of inventory" FROM inventories
WHERE product_id < 1775;
Decode 函式的主要使用:
求一箇中文排序方法,謝謝!
SELECT * FROM TEMP ORDER BY 傳送狀態;
傳送狀態 東城區 西城區 崇文區 宣武區 朝陽區 豐臺區 石景山區 海淀區 合計
成功 1,473 1,113 297 103 875 1,037 7 576 5,481
傳送中 144 3 14 0 30 0 11 8 210
合計 1,619 1,116 324 103 1,125 1,224 47 584 6,142
失敗 2 0 13 0 220 187 29 0 451
想按照如下順序排序,指定按照“傳送狀態”欄位“成功”-“傳送中”,“失敗”,"合計"的順序,即:
傳送狀態 東城區 西城區 崇文區 宣武區 朝陽區 豐臺區 石景山區 海淀區 合計
成功 1,473 1,113 297 103 875 1,037 7 576 5,481
傳送中 144 3 14 0 30 0 11 8 210
失敗 2 0 13 0 220 187 29 0 451
合計 1,619 1,116 324 103 1,125 1,224 47 584 6,142
SELECT * FROM TEMP ORDER BY DECODE(傳送狀態,'成功',1,'傳送中',2,....)
來源於select name,id from tmp order by 2;按列位置排序,使用decode則可以動態指定
主要使用在查詢結果的行列轉換上,如:
1、 固定列數的行列轉換
如
name subject grade
---------------------------
student1 語文 80
student1 數學 70
student1 英語 60
student2 語文 90
student2 數學 80
student2 英語 100
……
轉換為
語文 數學 英語
student1 80 70 60
student2 90 80 100
按照name分組得到的結果,所以decode外面要套個sum,不然group by出現語義錯誤,結果為
select name,sum(decode(subject,'語文', grade,null)) "語文",
sum(decode(subject,'數學', grade,null)) "數學",
sum(decode(subject,'英語', grade,null)) "英語"
from student
group by name
2、 不定列行列轉換
如
c1 c2
--------------
1 我
1 是
1 誰
2 知
2 道
3 不
……
轉換為
1 我是誰
2 知道
3 不
這一型別的轉換必須藉助於PL/SQL 來完成,這裡給一個例子
CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER)
RETURN VARCHAR2
IS
Col_c2 VARCHAR2(4000);
BEGIN
FOR cur IN (SELECT c2 FROM t WHERE c1=tmp_c1) LOOP
Col_c2 := Col_c2||cur.c2;
END LOOP;
Col_c2 := rtrim(Col_c2,1);
RETURN Col_c2;
END;
/
SQL> select distinct c1 ,get_c2(c1) cc2 from table;即可
或者不用pl/sql,利用分析函式和 CONNECT_BY 實現:
SELECT c1, SUBSTR (MAX (SYS_CONNECT_BY_PATH (c2, ';')), 2) NAME
FROM (SELECT c1, c2, rn, LEAD (rn) OVER (PARTITION BY c1 ORDER BY rn) rn1
FROM (SELECT c1, c2, ROW_NUMBER () OVER (ORDER BY c2) rn
FROM t))
START WITH rn1 IS NULL
CONNECT BY rn1 = PRIOR rn
GROUP BY c1;
3、列數不固定(交叉錶行列轉置)
這種是比較麻煩的一種,需要藉助pl/sql:
原始資料:
CLASS1 CALLDATE CALLCOUNT
1 2005-08-08 40
1 2005-08-07 6
2 2005-08-08 77
3 2005-08-09 33
3 2005-08-08 9
3 2005-08-07 21
轉置後:
CALLDATE CallCount1 CallCount2 CallCount3
------------ ---------- ---------- ----------
2005-08-09 0 0 33
2005-08-08 40 77 9
2005-08-07 6 0 21
試驗如下:
1). 建立測試表和資料
CREATE TABLE t(
class1 VARCHAR2(2 BYTE),
calldate DATE,
callcount INTEGER
);
INSERT INTO t(class1, calldate, callcount)
VALUES ('1', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 40);
INSERT INTO t(class1, calldate, callcount)
VALUES ('1', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 6);
INSERT INTO t(class1, calldate, callcount)
VALUES ('2', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 77);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/09/2005', 'MM/DD/YYYY'), 33);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 9);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 21);
COMMIT ;
2) 建立ref cursor準備輸出結果集
CREATE OR REPLACE PACKAGE pkg_getrecord
IS
TYPE myrctype IS REF CURSOR;
END pkg_getrecord;
/
3). 建立動態sql交叉表函式,輸出結果集
CREATE OR REPLACE FUNCTION fn_rs
RETURN pkg_getrecord.myrctype
IS
s VARCHAR2 (4000);
CURSOR c1 IS
SELECT ',sum(case when Class1='
|| class1
|| ' then CallCount else 0 end)'
|| ' "CallCount'
|| class1
|| '"' c2
FROM t
GROUP BY class1;
r1 c1%ROWTYPE;
list_cursor pkg_getrecord.myrctype;
BEGIN
s := 'select CallDate ';
OPEN c1;
LOOP
FETCH c1 INTO r1;
EXIT WHEN c1%NOTFOUND;
s := s || r1.c2;
END LOOP;
CLOSE c1;
s := s || ' from T group by CallDate order by CallDate desc ';
OPEN list_cursor FOR s;
RETURN list_cursor;
END fn_rs;
/
4). 測試在sql plus下執行:
var results refcursor;
exec :results := fn_rs;
print results;
CALLDATE CallCount1 CallCount2 CallCount3
--------------- ---------- ---------- ----------
2005-08-09 0 0 33
2005-08-08 40 77 9
2005-08-07 6 0 21
4、 不分組只簡單行列互換,並且每組之間用虛線分割,可以使用procedure,程式碼如下:
create or replace
procedure print_table(p_query in varchar2)
authid current_user as
l_thecursor integer default dbms_sql.open_cursor;
l_columnvalue varchar2(4000);
l_status integer;
l_desctbl dbms_sql.desc_tab;
l_colcnt number;
begin
dbms_sql.parse(l_thecursor,p_query,dbms_sql.native);
dbms_sql.describe_columns(l_thecursor,l_colcnt,l_desctbl);
for i in 1..l_colcnt loop
dbms_sql.define_column(l_thecursor,i,l_columnvalue,4000);
end loop;
l_status := dbms_sql.execute(l_thecursor);
while(dbms_sql.fetch_rows(l_thecursor)>0) loop
for i in 1..l_colcnt loop
dbms_sql.column_value(l_thecursor,i,l_columnvalue);
dbms_output.put_line(rpad(l_desctbl(i).col_name,30)||l_c
olumnvalue);
end loop;
dbms_output.put_line('----------------------------------------------
-------');
end loop;
exception
when others then
dbms_sql.close_cursor(l_thecursor);
raise;
null;
end;
/
Decode函式的語法結構如下:
decode (expression, search_1, result_1)
decode (expression, search_1, result_1, search_2, result_2)
decode (expression, search_1, result_1, search_2, result_2, ....,
search_n, result_n)
decode (expression, search_1, result_1, default)
decode (expression, search_1, result_1, search_2, result_2, default)
decode (expression, search_1, result_1, search_2, result_2, ....,
search_n, result_n, default)
作用:和case表示式實現的功能一樣,以第1 個引數為關鍵欄位,如果等於search,則結果為對應的result,最後匹配不到的結果為default。如果沒有寫default,返回null。 為了格式一致,建議匹配不到不返回結果時,寫null。如果第一個返回結果為char 或null,oracle自動轉型為varchar2,如下面例子
SELECT product_id,
DECODE (warehouse_id, 1, ’Southlake’,
2, ’San Francisco’,
3, ’New Jersey’,
4, ’Seattle’,
’Non-domestic’)
"Location of inventory" FROM inventories
WHERE product_id < 1775;
Decode 函式的主要使用:
求一箇中文排序方法,謝謝!
SELECT * FROM TEMP ORDER BY 傳送狀態;
傳送狀態 東城區 西城區 崇文區 宣武區 朝陽區 豐臺區 石景山區 海淀區 合計
成功 1,473 1,113 297 103 875 1,037 7 576 5,481
傳送中 144 3 14 0 30 0 11 8 210
合計 1,619 1,116 324 103 1,125 1,224 47 584 6,142
失敗 2 0 13 0 220 187 29 0 451
想按照如下順序排序,指定按照“傳送狀態”欄位“成功”-“傳送中”,“失敗”,"合計"的順序,即:
傳送狀態 東城區 西城區 崇文區 宣武區 朝陽區 豐臺區 石景山區 海淀區 合計
成功 1,473 1,113 297 103 875 1,037 7 576 5,481
傳送中 144 3 14 0 30 0 11 8 210
失敗 2 0 13 0 220 187 29 0 451
合計 1,619 1,116 324 103 1,125 1,224 47 584 6,142
SELECT * FROM TEMP ORDER BY DECODE(傳送狀態,'成功',1,'傳送中',2,....)
來源於select name,id from tmp order by 2;按列位置排序,使用decode則可以動態指定
主要使用在查詢結果的行列轉換上,如:
1、 固定列數的行列轉換
如
name subject grade
---------------------------
student1 語文 80
student1 數學 70
student1 英語 60
student2 語文 90
student2 數學 80
student2 英語 100
……
轉換為
語文 數學 英語
student1 80 70 60
student2 90 80 100
按照name分組得到的結果,所以decode外面要套個sum,不然group by出現語義錯誤,結果為
select name,sum(decode(subject,'語文', grade,null)) "語文",
sum(decode(subject,'數學', grade,null)) "數學",
sum(decode(subject,'英語', grade,null)) "英語"
from student
group by name
2、 不定列行列轉換
如
c1 c2
--------------
1 我
1 是
1 誰
2 知
2 道
3 不
……
轉換為
1 我是誰
2 知道
3 不
這一型別的轉換必須藉助於PL/SQL 來完成,這裡給一個例子
CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER)
RETURN VARCHAR2
IS
Col_c2 VARCHAR2(4000);
BEGIN
FOR cur IN (SELECT c2 FROM t WHERE c1=tmp_c1) LOOP
Col_c2 := Col_c2||cur.c2;
END LOOP;
Col_c2 := rtrim(Col_c2,1);
RETURN Col_c2;
END;
/
SQL> select distinct c1 ,get_c2(c1) cc2 from table;即可
或者不用pl/sql,利用分析函式和 CONNECT_BY 實現:
SELECT c1, SUBSTR (MAX (SYS_CONNECT_BY_PATH (c2, ';')), 2) NAME
FROM (SELECT c1, c2, rn, LEAD (rn) OVER (PARTITION BY c1 ORDER BY rn) rn1
FROM (SELECT c1, c2, ROW_NUMBER () OVER (ORDER BY c2) rn
FROM t))
START WITH rn1 IS NULL
CONNECT BY rn1 = PRIOR rn
GROUP BY c1;
3、列數不固定(交叉錶行列轉置)
這種是比較麻煩的一種,需要藉助pl/sql:
原始資料:
CLASS1 CALLDATE CALLCOUNT
1 2005-08-08 40
1 2005-08-07 6
2 2005-08-08 77
3 2005-08-09 33
3 2005-08-08 9
3 2005-08-07 21
轉置後:
CALLDATE CallCount1 CallCount2 CallCount3
------------ ---------- ---------- ----------
2005-08-09 0 0 33
2005-08-08 40 77 9
2005-08-07 6 0 21
試驗如下:
1). 建立測試表和資料
CREATE TABLE t(
class1 VARCHAR2(2 BYTE),
calldate DATE,
callcount INTEGER
);
INSERT INTO t(class1, calldate, callcount)
VALUES ('1', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 40);
INSERT INTO t(class1, calldate, callcount)
VALUES ('1', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 6);
INSERT INTO t(class1, calldate, callcount)
VALUES ('2', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 77);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/09/2005', 'MM/DD/YYYY'), 33);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 9);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 21);
COMMIT ;
2) 建立ref cursor準備輸出結果集
CREATE OR REPLACE PACKAGE pkg_getrecord
IS
TYPE myrctype IS REF CURSOR;
END pkg_getrecord;
/
3). 建立動態sql交叉表函式,輸出結果集
CREATE OR REPLACE FUNCTION fn_rs
RETURN pkg_getrecord.myrctype
IS
s VARCHAR2 (4000);
CURSOR c1 IS
SELECT ',sum(case when Class1='
|| class1
|| ' then CallCount else 0 end)'
|| ' "CallCount'
|| class1
|| '"' c2
FROM t
GROUP BY class1;
r1 c1%ROWTYPE;
list_cursor pkg_getrecord.myrctype;
BEGIN
s := 'select CallDate ';
OPEN c1;
LOOP
FETCH c1 INTO r1;
EXIT WHEN c1%NOTFOUND;
s := s || r1.c2;
END LOOP;
CLOSE c1;
s := s || ' from T group by CallDate order by CallDate desc ';
OPEN list_cursor FOR s;
RETURN list_cursor;
END fn_rs;
/
4). 測試在sql plus下執行:
var results refcursor;
exec :results := fn_rs;
print results;
CALLDATE CallCount1 CallCount2 CallCount3
--------------- ---------- ---------- ----------
2005-08-09 0 0 33
2005-08-08 40 77 9
2005-08-07 6 0 21
4、 不分組只簡單行列互換,並且每組之間用虛線分割,可以使用procedure,程式碼如下:
create or replace
procedure print_table(p_query in varchar2)
authid current_user as
l_thecursor integer default dbms_sql.open_cursor;
l_columnvalue varchar2(4000);
l_status integer;
l_desctbl dbms_sql.desc_tab;
l_colcnt number;
begin
dbms_sql.parse(l_thecursor,p_query,dbms_sql.native);
dbms_sql.describe_columns(l_thecursor,l_colcnt,l_desctbl);
for i in 1..l_colcnt loop
dbms_sql.define_column(l_thecursor,i,l_columnvalue,4000);
end loop;
l_status := dbms_sql.execute(l_thecursor);
while(dbms_sql.fetch_rows(l_thecursor)>0) loop
for i in 1..l_colcnt loop
dbms_sql.column_value(l_thecursor,i,l_columnvalue);
dbms_output.put_line(rpad(l_desctbl(i).col_name,30)||l_c
olumnvalue);
end loop;
dbms_output.put_line('----------------------------------------------
-------');
end loop;
exception
when others then
dbms_sql.close_cursor(l_thecursor);
raise;
null;
end;
/
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23590362/viewspace-660113/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- python中encode和decode函式說明Python函式
- Spark實現行列轉換pivot和unpivotSpark
- mysql行列轉換詳解MySql
- 報表如何實現行列互換效果?
- Oracle中Decode()函式的使用Oracle函式
- 記錄一個行列轉換
- 函式匹配和實參型別轉換函式型別
- python str與byte轉換 encode decodePython
- 實現二維陣列的行列互換陣列
- js顯式轉換和隱式轉換JS
- 8.轉換文字函式函式
- Oracle OCP(05):轉換函式Oracle函式
- Oracle行列轉換及pivot子句的用法Oracle
- mysql 時間相關的函式 以及日期和字串互轉MySql函式字串
- web 展現資料時如何實現行列互換Web
- Django筆記二十四之資料庫函式之比較和轉換函式Django筆記資料庫函式
- MySQL中日期和時間戳互相轉換的函式和方法MySql時間戳函式
- Restcloud ETl實踐之資料行列轉換RESTCloud
- GaussDB: db2->gaussdb 函式轉換DB2函式
- 使用vue實現行列轉換的一種方法。Vue
- python函式每日一講 - float函式型別轉換詳解Python函式型別
- Java資料型別的顯式轉換和隱式轉換Java資料型別
- 將數值轉換為字串的函式字串函式
- C++型別轉換建構函式C++型別函式
- sql server 資料型別轉換函式SQLServer資料型別函式
- 建構函式定義的隱式型別轉換函式型別
- Solidity語言學習筆記————11、隱式轉換和顯式轉換Solid筆記
- 將你的Gradle依賴轉換為函式Gradle函式
- 例項詳解構建數倉中的行列轉換
- EXCEL中日期格式轉換為文字格式-函式TEXTExcel函式
- 神經網路啟用函式=生物轉換器?神經網路函式
- scala簡明教程:偏函式、高階函式、Future非同步程式設計、隱式轉換函式非同步程式設計
- AI應用任何PDF轉換為互動式儀表盤AI
- 在報表中錄入資料時如何實現行列轉換
- 【Hive】字串替換函式translate和regexp_replaceHive字串函式
- c++中幾種常見的型別轉換。int與string的轉換,float與string的轉換以及string和long型別之間的相互轉換。to_string函式的實現和應用。C++型別函式
- Linux軟體包轉換-deb與rpm互轉Linux
- String 和Inputstreem互轉
- java隱式轉換Java