1. 程式人生 > >多行轉多列,行數和列數不確定

多行轉多列,行數和列數不確定

原始需求,有2表如下
SQL> select * from mas;

TO TOOLNAME
-- ----------
01 包裹
02 信函
03 掛號信
04 中國速遞
05 EMS
06 DHL

6 rows selected.

SQL> select * from putdt;

SENDDT TO GNAME ST CITY
-------- -- ---------- -- ----
20070101 01 john 12 2566
20070101 04 david 16 3098
20070101 05 apple 18 2098
20070201 04 apple 16 3078
20070304 05 poly 13 1001
20070304 04 john 12 2566
20070101 01 james 12 8800

7 rows selected.

要求輸出如下格式的報表
senddt toolid1 sum1 toolid2 sum2 toolid3 sum3 toolid4 sum4 toolid5 sum5
20070101 01 1 02 0 03 0 04 1 05 1
20070201 01 0 02 0 03 0 04 1 05 0
20070304 01 0 02 0 03 0 04 1 05 1
即以senddt和toolid分組後的count數
每行顯示一個senddt,但是列數是不確定的,根據表mas的toolid來定的

基本思路如下,如下的SQL 是動態構造的,其中的列數不確定,根據mas的toolid來定
select senddt,
max(toolid1) toolid1,max(sum1) sum1,
max(toolid2) toolid2,max(sum2) sum2,
max(toolid3) toolid3,max(sum3) sum3,
max(toolid4) toolid4,max(sum4) sum4,
max(toolid5) toolid5,max(sum5) sum5
from (select b.senddt,
'01' toolid1,
case when a.toolid=b.toolid and b.toolid='01' then b.sum_c else 0 end sum1,
'02' toolid2,
case when a.toolid=b.toolid and b.toolid='02' then b.sum_c else 0 end sum2,
'03' toolid3,
case when a.toolid=b.toolid and b.toolid='03' then b.sum_c else 0 end sum3,
'04' toolid4,
case when a.toolid=b.toolid and b.toolid='04' then b.sum_c else 0 end sum4,
'05' toolid5,
case when a.toolid=b.toolid and b.toolid='05' then b.sum_c else 0 end sum5
from mas a,
(select senddt,toolid,count(*) sum_c from putdt group by senddt,toolid) b)
group by senddt
order by senddt

測試用的儲存過程
create or replace procedure test
as
v_column varchar2(5) := '';
v_sql_0 varchar2(10000) := '';
v_sql_1 varchar2(10000) := '';
p_fields varchar2(10000) := '';
begin
for t in (select toolid from mas order by toolid) loop
v_column := to_char(to_number(t.toolid));
v_sql_0 := v_sql_0||',max(toolid'||v_column||') toolid'||v_column||',max(sum'||v_column||') sum'||v_column;
v_sql_1 := v_sql_1||','''||t.toolid||''' toolid'||v_column||', case when a.toolid=b.toolid and b.toolid='''||t.toolid||''' then b.sum_c else 0 end sum'||v_column;
p_fields := p_fields||',toolid'||v_column||',sum'||v_column;
end loop;
v_sql_1 := 'select senddt'||v_sql_0||' from (select b.senddt'||v_sql_1||' from mas a,(select senddt,toolid,count(*) sum_c from putdt group by senddt,toolid) b) group by senddt order by senddt';
p_fields := ltrim(p_fields,',');
--open p_rs for v_sql_1;
dbms_output.put_line(v_sql_1);
end;
/

--------------
1. 建立package
--------------

create or replace package pkg_test
as
type cursor_fount100 is ref cursor;
procedure rs_fount100 (p_fields in out varchar2,p_rs in out cursor_fount100);
end;
/

create or replace package body pkg_test
as
procedure rs_fount100 (p_fields in out varchar2,p_rs in out cursor_fount100)
is
v_column varchar2(5) := '';
v_sql_0 varchar2(10000) := '';
v_sql_1 varchar2(10000) := '';
begin
for t in (select toolid from mas order by toolid) loop
v_column := to_char(to_number(t.toolid));
v_sql_0 := v_sql_0||',max(toolid'||v_column||') toolid'||v_column||',max(sum'||v_column||') sum'||v_column;
v_sql_1 := v_sql_1||','''||t.toolid||''' toolid'||v_column||', case when a.toolid=b.toolid and b.toolid='''||t.toolid||''' then b.sum_c else 0 end sum'||v_column;
p_fields := p_fields||',toolid'||v_column||',sum'||v_column;
end loop;
v_sql_1 := 'select senddt'||v_sql_0||' from (select b.senddt'||v_sql_1||' from mas a,(select senddt,toolid,count(*) sum_c from putdt group by senddt,toolid) b) group by senddt order by senddt';
p_fields := ltrim(p_fields,',');
open p_rs for v_sql_1;
end;
end;
/

----------------------------
2. JAVA程式 test.java 演示用
----------------------------

import java.io.*;
import java.text.*;
import java.lang.String;
import java.util.*;
import java.util.regex.*;
import java.lang.*;
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.driver.*;

public class test
{
public static void main(String[] args) throws Exception
{
String record_str="";
String field_list="";
String[] fields=null;
Pattern p = Pattern.compile(",");
Matcher m1;
OracleCallableStatement cstmt = null;
ResultSet rs = null;
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.1:1521:例項名","資料庫使用者","密碼");
cstmt = (OracleCallableStatement)conn.prepareCall("begin pkg_test.rs_fount100(?,?); end;");
cstmt.registerOutParameter(1,OracleTypes.VARCHAR);
cstmt.registerOutParameter(2,OracleTypes.CURSOR);
cstmt.execute();
field_list = cstmt.getString(1);
rs = (ResultSet)cstmt.getObject(2);
fields=p.split(field_list);
for(int i=0; i<fields.length; i++)
{
record_str=record_str+fields[i]+" ";
}
System.out.println("senddt "+record_str);
while (rs.next())
{
record_str="";
for(int f=1; f<=fields.length+1; f++)
{
record_str=record_str+rs.getString(f)+" ";
}
System.out.println(record_str);
}
rs.close();
cstmt.close();
conn.close();
}
}

---------------
3. 編譯java程式
---------------
javac test.java

---------------
4. 演示1
---------------

SQL> select * from mas;

TO TOOLNAME
-- ----------
01 包裹
02 信函
03 掛號信
04 中國速遞
05 EMS

SQL> select * from putdt;

SENDDT TO GNAME ST CITY
-------- -- ---------- -- ----
20070101 01 john 12 2566
20070101 04 david 16 3098
20070101 05 apple 18 2098
20070201 04 apple 16 3078
20070304 05 poly 13 1001
20070304 04 john 12 2566

6 rows selected.

E:>java test
senddt toolid1 sum1 toolid2 sum2 toolid3 sum3 toolid4 sum4 toolid5 sum5
20070101 01 1 02 0 03 0 04 1 05 1
20070201 01 0 02 0 03 0 04 1 05 0
20070304 01 0 02 0 03 0 04 1 05 1


---------------
5. 演示2
---------------

SQL> insert into putdt values('20070101','01','james','12','8800');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from putdt;

SENDDT TO GNAME ST CITY
-------- -- ---------- -- ----
20070101 01 john 12 2566
20070101 04 david 16 3098
20070101 05 apple 18 2098
20070201 04 apple 16 3078
20070304 05 poly 13 1001
20070304 04 john 12 2566
20070101 01 james 12 8800

7 rows selected.

E:>java test
senddt toolid1 sum1 toolid2 sum2 toolid3 sum3 toolid4 sum4 toolid5 sum5
20070101 01 2 02 0 03 0 04 1 05 1
20070201 01 0 02 0 03 0 04 1 05 0
20070304 01 0 02 0 03 0 04 1 05 1


---------------
6. 演示3
---------------
SQL> insert into mas values('06','DHL');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from mas;

TO TOOLNAME
-- ----------
01 包裹
02 信函
03 掛號信
04 中國速遞
05 EMS
06 DHL

6 rows selected.

SQL> select * from putdt;

SENDDT TO GNAME ST CITY
-------- -- ---------- -- ----
20070101 01 john 12 2566
20070101 04 david 16 3098
20070101 05 apple 18 2098
20070201 04 apple 16 3078
20070304 05 poly 13 1001
20070304 04 john 12 2566
20070101 01 james 12 8800

7 rows selected.

E:java test
senddt toolid1 sum1 toolid2 sum2 toolid3 sum3 toolid4 sum4 toolid5 sum5 toolid6 sum6
20070101 01 2 02 0 03 0 04 1 05 1 06 0
20070201 01 0 02 0 03 0 04 1 05 0 06 0
20070304 01 0 02 0 03 0 04 1 05 1 06 0

[@[email protected]]

相關推薦

確定

原始需求,有2表如下 SQL> select * from mas; TO TOOLNAME -- ---------- 01 包裹 02 信函 03 掛號信 04 中國速遞 05 EMS 06 DHL 6 rows selected. SQL> select * from putdt; SEN

行列轉換之——實踐版

多行 max 演示 spa info 思想 .com 要求 列轉行 行列轉換之——多行轉多列,多列轉多行實踐版 1、多列轉行(核心思想,利用row_number() over() 來構造列傳行之後的唯一列,來行轉列)   要求:     實操演示: select

hiveLATERAL VIEW explode

lateral view用於和split、explode等UDTF一起使用的,能將一行資料拆分成多行資料,在此基礎上可以對拆分的資料進行聚合,lateral view首先為原始表的每行呼叫UDTF,UDTF會把一行拆分成一行或者多行,lateral view在把結果組合,產生一個支援別名表的

SQL

表內容: 姓名 課程 分數 張三 語文 74張三 數學 83張三 物理 93張三 德語 null李四 語文 74李四 數學 84李四 物理 94李四 英語 80想變成(得到如下結果): 姓名 語文 數學 物理 英語 德語---- ---- ---- ----李四 74   

mysql

開發十年,就只剩下這套架構體系了! >>>   

實現一個函式列印乘法口訣表口訣表的自己指定 輸入9輸出9*9口訣表輸入12輸出12*12的乘法口訣表。

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main() { int n = 0; printf("請輸入一個數:"); scanf("%d", &n);

C#中如何獲取一個二維陣列的兩維長度

int[,] array = new int[,] {{1,2,3},{4,5,6},{7,8,9}};//定義一個3行3列的二維陣列 int row = array.Rank;//獲取行數 int col = array.GetLength(1);//獲取指定維中的元 個

用C語言中的函式列印乘法口訣表可以任意輸入

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> void print_table(int line) { int i = 0;

Java 組 獲取二維組的

怎樣 tps lan 個數 元素 mil family 資料 object   對於Object[][] array,array.length返回行數,array[0].length返回列數,元素個數為array.length*array[0].length。   參考

C#中二維組的

取數 word 二維數組 同學 定義 dimen 行數 nbsp col 最近在項目中用到二維數組,需要獲取數組的行數和列數,本以為是很簡單的一些東西,卻發現網上好多答案都是錯誤的,遂寫下隨筆,希望之後有用到的同學們能夠順利解決答案。 下面是一些關於數組的一些屬性和方法以及

VBA取得EXCEL表格中的

VBA取得EXCEL表格中的行數和列數       初學EXCEL巨集的童鞋,總是很想知道表格中含有資料的行數和列數,尤其是行數和列數不確定的情況下。這樣可以避免很多的錯誤,並且可以提高效率。但每次用到的時候到網上查詢時,總是給了很多無用的答案,往往找不到想要的

VS 計算二維陣列的

對於一個二維陣列如: int a[2][5]; 求陣列元素的總數: sizeof(a) / sizeof(int) 而陣列行數則為 :( sizeof(a) / sizeof(int) )/ ( sizeof(a[0]) / sizeof(int) ) 求陣列列數: si

C#獲取陣列的

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test02 {     class Program     {        

2017.8.19 利用python統計文件中的單詞數字元

file_name='a.txt' line_count=0 word_count=0 character_count=0 with open(file_name,'r',encoding='utf-

獲取ResultSet的

獲取ResultSet行數時需要使用可回滾的遊標,自定義方法,獲取行數後要回滾,獲取ResultSet列數時通過ResultSetMetaData類的getColumnCount方法即可獲得。 示例程式碼: publicclass Test ...{    publicsta

2.統計輸入的單詞字元

#include <stdio.h> #define IN 1 #define OUT 0 int main() { int c, nl, nw, nc, state; state = OUT; nl = nw = nc

用VBA得到EXCEL表格中的

方法3:   ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row   ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Column   缺點:在工作表進行對刪除或清除操作時也會變得比實際情況大。方法

如何獲取ResultSet的

當我們執行資料庫查詢返回一個ResultSet的時候,很多情況下我們需要知道這個ResultSet的大小,即它的行數和列數。我們知道它的列數可以通過resultSet.getMetaData().getColumnCount()很容易地得到,然而,java API沒有提供直接訪問ResultSet行數的介面