九月份複習,十月份考試,十月底一直無法收心,趕在十一初 因爲不可抗拒的緣由又不得不從新找工做就;欸~, 又是一番折騰,從入職到如今,可又無法閒下來了...
這種方式sql難度低,可是容易給DB形成較大的開銷,畢竟每一個最終的列的值都是一個聚合函數的值,同時非聚合列也要隨聚合列而定,大多數狀況下可能須要將多個子查詢連表查;至於在mybatis中的時候就很是簡單了,這裏就再也不綴訴哈~
此種方式有一個缺點是:一次查詢只能對一個列的數據進行拆分(成多列),如需對多列拆分,則可行的方式是作多個查詢,一個查詢拆分一列(同時保留鏈接字段), 同時,這裏須要主要的是 在 pivot 下的in中不能夠是一個子查詢,記得當時調試的時候怎麼調試就是報錯,後來翻了翻英文網站的說明,給的大體意思是這個pivot內拆分的目標字段不能夠是一個子查詢,只能是寫死的列 ,其實也不是不能夠,只是官方給出的說法是:要實現動態列,只能使用xml的方式(說了等於沒說)。 ok,待SQL調試完畢,copy到應用中使用的時候仍是會報錯,這個時候就須要注意到mybatis的一些基本約定,就是傳值方式,mybatis的傳值方式大體有#{value}和${value}兩種方式 ,#符號定義的值實際上是將整個值對象交給DBMS去處理,而$符號定義的值是將值直接放入到語句內,對DBMS來講,後者更至關於一個定值,因此將povit應用在mybatis中須要使用$的值定義方式(僅在in內這樣使用,pivot外視業務狀況而定)。 同時,由於使用$符號定義值的方式不時mybatis並不會將傳入的值做爲一個String字符來處理,若是是日期及其餘類型儘可能使用string的方式將值傳入,拆分的值如果日期類型的須要 使用to_date()函數或者_to_char()_函數進轉換纔是,若是目標值就是String類型且必定要將整個聲明值使用單引號引發來('#{value}'),另外,拆分的目標列也是能夠定義別名的,否則DB 又會給出pivot內不能使用動態語句的錯誤,須要使用CDATA標籤作xml轉義,最終的樣子大體就是這樣 : in (to_date('${value}','b') as <![CDATA[${key}]],to_date('${value}','b') as <![CDATA[${key}]]>)
這種方式其實很容易將sql寫的很複雜,主要有兩個方面:一個是wm_concat 函數必定要指定partition by和order by的字段,就是組內分組和組內排序方式,否則最終的結果數據混亂不堪(除非這對你的業務不重要),另外一個緣由是窗口函數自己是不會聚合行,因此,組內拼接也是順序拼接,因此須要作的就是將非結果行去掉纔是,這個時候就須要使用另外一個窗口函數rank(),這個函數是對組內作排序,因爲目標是實現行轉列,因此此時就須要將rank()的排序方式改成desc,然後再作一個子查詢將rank的值爲非1的全去掉。 因爲使用wm_concat的結果是單列,須要此時須要根據逗號作分隔,截取爲指定的列,wm_concat函數使用起來並不難,可是面對實際業務的時候,如果大數據量就得慎重咯,由於函數使用的越多就越容易形成DB的開銷,這個是不容忽視的。 wm_concat在mybatis中的使用並無障礙,須要注意的細節是拼接字段可能不是varchar類型,而是blob(大字段)類型,須要用to_char()函數作轉換,同時wm_concat函數只能按照逗號進行內容拼接,若是字符包含逗號,建議將wm_concat內的源字段拼接一個惟一字符。
此種方式同以上的pivot的方式相反,不過好處是他不會有行轉列的單列問題,至於在mybatis中的使用,建議參照以上pivot的方式
其實這個函數的說的意義並不大,由於regexp_substr函數在拆分十行數據的時候DB的開銷就顯現出來了,若是不得已要用的話首先推薦使用程序來處理,若是使用數據庫處理,建議將 目標數據拆分多個組來作,建議不要超過十個,並且拆分的列的數據複雜度不能過高(字符太長,正則太複雜),在mybatis下的使用中只須要注意下目標列的類型,必要時使用to_char函數進行轉換纔是~
相信你們已經猜出一部分了,這裏簡要說下這三個東東大概是幹什麼:level實現級的序號增長,connect by 實現遞歸,rownum則配合運算結果加減,如下就給出具體的SQL,可 直接執行。
SELECT TO_DATE('2018-10-28','YYYY-MM-DD')+ROWNUM - 1 DT FROM DUAL CONNECT BY LEVEL <=(TO_DATE('2018-11-20','YYYY-MM-DD')-TO_DATE('2018-10-28','YYYY-MM-DD')+1)
貌似不使用rownum也是能夠的,各位能夠嘗試下哈~
#### 最後,本來在寫博客前在我的電腦中跑一個oracle的,實際安裝的過程當中發現oracle的安裝包實在是太大了,許久不安裝,安裝過程不免也會出現各類問題,遂~就放棄了,改天我會盡可能將語句都放出來,以饗廣大讀者哈~,至於行轉列列轉行的實現方式就給個粗糙的sql你們嘗試着看哈~~
-- 行轉列
SELECT * from
(
SELECT tt1.SAP_ID,TT1.dt,TT1.EFF from (
SELECT t1.SAP_ID,T1.DT,nvl(T2.EFFECTIVE,0) eff from
(
SELECT A1.SAP_ID,mr.dt from
(SELECT DISTINCT SAP_ID from DATA_EMP_ATTENDANCE) a1,
(SELECT TO_DATE('2018-11-01','YYYY-MM-DD')+ROWNUM - 1 DT
FROM DUAL CONNECT BY LEVEL <=(TO_DATE('2018-11-15','YYYY-MM-DD')-TO_DATE('2018-11-01','YYYY-MM-DD')+1)) mr
) t1
LEFT JOIN
(
SELECT SAP_ID,BEGIN_DATE,1 effective from DATA_EMP_ATTENDANCE
) t2
ON T2.SAP_ID = T1.SAP_ID AND T2.BEGIN_DATE = T1.DT
ORDER BY t1.dt DESC
) tt1
) pivot
(max(eff) for dt in (to_date('2018-11-05','yyyy-mm-dd') d1,to_date('2018-11-12','yyyy-mm-dd') d2,to_date('2018-11-12','yyyy-mm-dd') d3));
```html