將乙個表的查詢結果作為另一查詢的字段(動態查詢列)

2021-05-23 01:09:44 字數 3497 閱讀 4008

城市1  城市2   城市3   城市4

2010-06      0      1         0         0

2010-08      0      1         0         2

2010-07      0      0         1         0

2010-05      1      0         0         0

時間和記錄都是從sino_user查詢出來的,而列名是從sino_ip表中查詢出來。本來用列舉法,直接把所有城市都用case when進行判斷一遍就ok,但是,sino_ip表中城市個數是不定的,就是說今天查詢出來時4個城市,明天也許就是5個城市。這就需要我們的統計能支援列的動態新增。我第一想到的是試圖(view),但是這個試圖怎麼寫,才能保證動態生成列呢,這就要使用動態sql,而動態sql在**生成能,嘿嘿,說了半天總算到正題了,沒錯,就是儲存過程。可以使用儲存過程動態生成view,然後根據view來查詢。

1、資料基礎

表結構我就不寫了,和上篇博文一樣的。

2、問題分析

select s.dd

,sum(city1) 城市1

,sum(city2) 城市2

,sum(city3) 城市3

,sum(city4) 城市4

,sum(city5) 城市5

from (select substr(to_char(t.update_time,'yyyy-mm-dd'),1,7) dd

,case when t1.city ='城市1' then 1 else 0 end city1

,case when t1.city ='城市2' then 1 else 0 end city2

,case when t1.city ='城市3' then 1 else 0 end city3

,case when t1.city ='城市4' then 1 else 0 end city4

,case when t1.city ='城市5' then 1 else 0 end city5

from sino_user t , sino_ip t1

where f_ip2number(t.ip) between f_ip2number(t1.ip_begin) and f_ip2number(t1.ip_end)) s group by s.dd

我們可以發現,sum部分和case when 部分都可以通過迴圈來新增,因此,我們可以把從城市對應ip段表中查詢出來的資料存放在游標中,通過迴圈來生成統計sql。

let's do it。

3、編寫過程

create or replace procedure p_count is

v_sql dbms_sql.varchar2s;

l_cursor integer default dbms_sql.open_cursor;

l_rows number default 0;

i number default 2;

begin

v_sql(1) := 'create or replace view v_count as select s.dd';

for c_col in (select id,city from sino_ip order by id) loop

v_sql(i) :=  ',sum(city' ||c_col.id||') '||c_col.city;

i := i+1;

end loop;

v_sql(i) := 'from (select substr(to_char(t.update_time,''yyyy-mm-dd''),1,7) dd';

for c_col2 in (select id,city from sino_ip order by id) loop

v_sql(i+1) :=  ',case when t1.city ='''||c_col2.city||''' then 1 else 0 end city'|| c_col2.id;

i:= i + 1;

end loop;

v_sql(i+1) := 'from sino_user t , sino_ip t1 ';

v_sql(i+2) := 'where f_ip2number(t.ip) between f_ip2number(t1.ip_begin) and f_ip2number(t1.ip_end)) s group by s.dd';

dbms_sql.parse(c => l_cursor,statement => v_sql,lb => v_sql.first,ub => v_sql.last,lf*** => true,language_flag => dbms_sql.native );

l_rows := dbms_sql.execute(l_cursor);

dbms_sql.close_cursor( l_cursor );

dbms_output.put_line(l_rows);

exception

when others then

dbms_output.put_line(sqlerrm);

end p_count;

注:過程中用到的f_ip2number函式可以到另乙個博文「如何使用sql查詢ip位址所屬ip段 」裡面去看,我就不再贅述。

大家可能注意到,我的在儲存過程中用來存放動態sql不是用varchar2,用的是dbms_sql.varchar2s,這是因為varchar2只能存放32k的字元,而我們的sql是很長,將來會更長,因此使用dbms_sql.varchar2分行來儲存sql。

同時,sql的執行也不能使用execute immediate,因為它也只能執行32k的sql,我們使用dmbs_sql.parse,通過游標來執行。

ok,執行。

報錯了.....

沒有足夠的許可權。

呵呵,我們在pl/sql中建立檢視需要建立檢視的許可權。

ok,我們給賬號個create any view的許可權。

執行沒報錯。

我們來查詢view

select * from v_count t

結果出來了,和我上面寫的要求一樣。

那我們來驗證它能不能動態生成列。

我們在sino_ip插入城市5,乙個新的ip段,然後在sino_user表中插入一條ip資料城市5的記錄。再來查詢:

城市1  城市2   城市3   城市4   城市5

2010-06       0       1          0         0        0

2010-08       0       1          0         2        0

2010-07       0       0          1         0        0

2010-05       1       0          0         0        1

ok,成功了。哈哈

虧了今天胡老大到我們那視察,不用上班,我才有空把最近做的東西記下來。

MySQL將查詢結果插入到另乙個表中

1 如果兩張表 查詢表和插入表 的字段一致,並且希望插入查詢表的全部資料,可以用此方法 insert into 目標表 select from 表 insert into user login1 select from user login 2 如果只希望插入指定字段,可以用此方法,注意兩表的字段型...

Hive實驗 將 查詢結果儲存到另乙個表中

查詢employee表,按部門分組,女性個數降序排序,將結果employee res表中 欄位為 部門id,女性個數 建表 建立表 employee hive create external table employee sid string,jdata string,name string,cit...

將乙個表的結果集插入到另乙個表中

舉例1 insert into table b time,score,totalscore select time,score,sum score over order bytime from table a 舉例2 insert into jobinfo analysis salary,addre...