日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle行列转换的思考与总结

發布時間:2023/12/4 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle行列转换的思考与总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近幾天一直在弄Oracle-SQL的問題,涉及到了一些平時沒有用到的東西,也因此而在這里郁悶了好久。現在問題得到了解決雖說不算完美。但是還是和大家一起分享一下。

行列轉換之一:sum(case when.. then.. else.. end)?as?語句

這種也可能是我們遇到的第一個行列轉換的方法。巧妙的利用匯總和判斷語句就可以解決的。

先看一個簡單的基礎表:如下圖

create table STUDENT
(
? STUNAME????? NVARCHAR2(50),
? SUBJECTNAME? NVARCHAR2(50),
? SUBJECTSCORE NUMBER
)

?

表中有兩個人的成績,每一行代表每個學生該學科的成績。這個也是我們初學SQL時候很常見的一個表結構了。

要求:把上面的多行值以學生為單位轉化為2行值,可以很直觀的看出每個學生的各科成績。于是乎便有了下面的語句。

select??
s.stuname,
sum(case when s.subjectname='語文' then? s.subjectscore else 0 end? )? as 語文成績,
sum(case when s.subjectname='數學' then? s.subjectscore else 0 end? )? as 數學成績,
sum(case when s.subjectname='英語' then? s.subjectscore else 0 end? )? as 英語成績
from student s
group by s.stuname
order by s.stuname

執行后所得結果:

上面的做法也很容易讓人理解,在這里就不多說了,但是上面的也是有局限性的。因為此處畢竟存在著一些固定值。比如case? 中的“語文,數學。。”不過遇到小的業務需求,還是可以拿來直接用的。比如一個學生成績管理系統這個就可以滿足了。

行列轉換之二:sys_connect_by_path系統函數,自定義函數,connect by sname = prior sname and rank-1 = prior rank遞歸?語句

素材還是上面的表,下面我想得到的結果是:

把一個對象的各個學科的屬性連接起來放入到一個列中,用字符串存放。

當時看到這個業務需求的時候,當然學生這個只是舉個例子。很沒有頭緒。但是業務那邊也急著要數據,沒辦法。只好硬著頭皮想辦法。首先就想起了這個要用連接字符串的函數,還需要判斷循環之類的。于是乎就想起了這樣做,創建一個自定義函數。來處理字符串不斷的相加。

方法1:自定義函數,循環

CREATE OR REPLACE FUNCTION getallsubject(parameter varchar2)--有參數方法,字符串
RETURN varchar2
IS
return_str varchar2(4000);--該方法返回一個字符串。
BEGIN
FOR rs IN?
(
SELECT? s.subjectname||':'||s.subjectscore as allshow?
FROM student s
WHERE s.stuname=parameter--當參數一直符合條件 for循環插入結果集rs
) LOOP
return_str:=return_str||rs.allshow;--loop所有字符串,相加
END LOOP;
RETURN return_str;
END;

執行select s.stuname,getallsubject(s.stuname) from? student s

可見,改方法對每一行值都進行了判斷,產生了多條記錄。然后select distinct s.stuname,getallsubject(s.stuname) from? student s

效果:

得到了想要的結果。

方法2:利用oracle自帶的sys_connect_by_path

要說明的是:

所以在使用這個函數之前,我們必須先對源數據進行處理。第一步簡單的處理一下。

create table stu1 as

select s.stuname sname,s.subjectname||s.subjectscore? sshow from student s

--
select *from stu1

如下所示:

OK下面就可以寫語句了。

select sname as 姓名,allstr 詳細描述 from?
(
? select sname,allstr,
? row_number() over(partition by sname order by sname,curr_level desc) ename_path_rank
? from (
???????? select sname,sshow,rank,level as curr_level,
???????? ltrim(sys_connect_by_path(sshow,','),',') allstr from --把所有字符串相加
???????? (
?????????? select s1.sname,s1.sshow,row_number() over(partition by s1.sname order by s1.sname,s1.sshow) rank
?????????? from stu1 s1 order by s1.sname,s1.sshow--創建樹關系,name可以作為parentid,rank可以作為childid
???????? ) connect by sname = prior sname and rank-1 = prior rank
?????? )
)
where ename_path_rank=1;

執行結果:

也得到了我們想要的結果。當然不用學科之間的間隔符我們可以用replace函數自定義。

比較復雜一點的行列轉換用以上兩個方法都可以實現。但是這兩個方法卻都存在著一些優點和缺點。但是本人建議還是使用下面的方法比較靠譜。

雖然結合上面的各種方法解決了這個問題,但是Oracle中字符類型值不能大于4000字節這個問題還一直沒解決。我在想有沒有一種數據類型,我可以往里面想放多少字節就可以放多少字節的呢。。歡迎各位高手指導!希望可以幫得上遇到該問題的或者是即將遇到該問題的朋友們。

轉載于:https://www.cnblogs.com/shengs/p/4089273.html

總結

以上是生活随笔為你收集整理的Oracle行列转换的思考与总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。