2019/8/29

SQL Pivot 範例


在SQL 2008以後的MSSQL中,PIVOT函數可將指定資料庫欄位的值產生分類小計後橫向展開,達到交叉表的效果。

舉例而言有個資料表叫做PLAN,裡面有兩個欄位 SCHOOL_NO,ACTION_CODE記載學校代碼與學校申請的項目。
若我們要知道每間學校每個申請項目的筆數,直覺會用 group by去小計,
但這樣查出來的結果還是一列一列的,並不會橫向展開。
select SCHOOL_NO,ACTION_CODE, count(*) group by SCHOOL_NO,ACTION_CODE 
 

清大 1 3 
清大 2 2 
清大 3 11 
政大 3 3 

可是一般正常人習慣看的,是將結果列出來的情形,比較清楚易懂。
     1 2 3 
清大 3 2 11 
政大 0 0 3 
 
筆者是從SQL2000開始學習的,以前必須先將結果 用case when ACTION_CODE = '2' then count else 0 的方式,
將每一個可能的結果擺到橫軸顯示。
但在SQL 2005以後提供了pivot函數,就不需要這樣做(仍須看貴司DBA設定DB的相容等級>=90才能使用)。
以下面的範例,查詢區塊t先過濾出要彙整計算的資料集,
第一個欄位通常是學校或部門代碼
區塊p 則是告訴SQL 要用哪一個欄位計算小計
先輸入是要計算筆數或是加總
for 語法則讓您輸入要列出統計的欄位值,如果想看ACTION_CODE的值是1,2,3的
要寫成 [1],[2],[3]而不是一般 SQL 用兩個單引號包起來的樣式。
如果要顯示的是每月的薪資小計,就會是[1],[2]....一直列到12去了。


 SELECT c.SCHOOL_NAME, p.* 
 FROM (
  select  SCHOOL_NO,ACTION_CODE
   from PLAN  
   where PLAN_ID like'%1A%'
   --and STATUS in ('0','1','2')
 ) as t 
 PIVOT (
  count(ACTION_CODE) 
  FOR ACTION_CODE IN ([2],[21],[22])
 ) as p
 left join SCHOOL as c
 on p.SCHOOL_no = c.SCHOOL_NO
 where p.[2] >0 

如果選項非常多,又要手工輸入所有項目,感覺有點瞎?
這時候可以利用SQL內宣告變數搭配select語法,兜出字串再塞到 Pivot裡。


DECLARE @ParaList NVARCHAR(MAX), @PivotSQL NVARCHAR(MAX) 
 
SELECT @ParaList = COALESCE(@ParaList + ',' ,'' ) + QUOTENAME(SCHOOL_NO) 
FROM SCHOOL 
GROUP BY QUOTENAME(SCHOOL_NO) 

print @ParaList
完成版
/*宣告變數*/
 DECLARE @ParaList NVARCHAR(MAX), @PivotSQL NVARCHAR(MAX) 

/*用現有資料表欄位值組出分類列表*/
/*這裡不能用distinct,不然只會出現第一筆 */
SELECT  @ParaList = COALESCE(@ParaList + ',' ,'' ) + QUOTENAME(rtrim(ACTION_CODE)) 
FROM PROFESSION_PLAN  
group by ACTION_CODE
print  @ParaList

 /*將查詢語法改為一段TSQL,帶入參數後用sp_executesql執行*/

 SELECT @PivotSQL = N'
 SELECT c.SCHOOL_NAME, p.* 
 FROM (
  select  SCHOOL_NO,ACTION_CODE
   from PROFESSION_PLAN  
   where  PROFESSION_PLAN_ID like''%1A%''
   --and STATUS in (''0'',''1'',''2'')
 ) as t 
 PIVOT (
  count(ACTION_CODE) 
  FOR ACTION_CODE IN (' + @ParaList +  N')
 ) as p
 left join SCHOOL as c
 on p.SCHOOL_no = c.SCHOOL_NO
 where p.[2] >0 
 '
 
EXEC sp_executesql  @PivotSQL;

2019/8/3

窮查理的普通常識(增訂版)精華 poor Charlie's ALMANACK

《窮查理的普通常識》是巴菲特的投資夥伴─李察‧蒙格的作品,問世多年了。原文書名的ALMANACK是一個古字,原意有點像農民的農民曆,後來引申為年鑑或老生常談。翻譯者翻成普通常識似乎略微遜色,也許對台灣的讀者而言,稱作碎碎念更為適切。

本書分為譯者的評述,以及蒙格本人的演講集。摘錄本人覺得不錯的重點如次:


  • 遠離毒品、嫉妒;避免做事反覆無常、避免不借鑑前人的經驗。不要意志消沉。重視風險管理(我只想知道我會死在甚麼地方,這樣我就可以永遠不去那裏。)
  • 永遠反向思考。
  • 學會有承擔、可靠。作者認為麥當勞平凡但值得尊敬,她為數百萬少年提供第一份工作,讓青少年學會承擔工作的責任。


─第一講

  • 投資之前要學習數學、會計學、統計學、心理學的一些基本觀念,用比較寬廣的思想體系看待投資。
  • 規模經濟降低成本開銷,龐大的曝光率帶來資訊優勢與社會認同。但規模太大也有缺點,不夠專業。廣泛性報導的雜誌,營收可能輸給有專業需求的專門雜誌。縮小規模、加強專業化程度,能夠帶來巨大的優勢。
  • 組織太大變成官僚化、分工變成偷懶的藉口。官僚作風搞倒西屋電器。
  • 對於鄉村雜貨店被量販店打敗,不要有懷舊情懷與幻覺。
  • 要考慮規模與經營熱情加在一起時產生的威力,精簡、刻薄、效率會打敗企業競爭對手的官僚風氣。
  • 某些行業會爆發割喉戰,大者恆大;某些行業則人人賺錢,擠掉別人並不經濟。
  • 導入新技術不只要考慮降低當下成本,也要考慮幾年後的實質報酬。
  • 破壞性創新對行業可能是競爭性毀滅。
  • 股票投資要考慮自身理解能力的能力圈。
  • 贏家謹慎出手。
  • 投資顧問要績效,總是逼你交易她才有收入。可是現在是時機點嗎?
  • 不要迷信換股操作
  • 如何提升效率?→不以時數計算,以件或班次算,做完就回家。
  • 投資有偉大領導者的優質企業,靠他們幫自己賺錢。然後長期持有。
─第二講


  • 掌握學科的理論模型
  • 查檢表的威力



  • 跨領域
  • 善用不同學科知識來解決問題
  • 軟科學要模仿硬科學實事求是的鑽研精神,在學科精華的訓練要更嚴格,針對某些學科的基本原理必須熟記,以此去思考事物,若有衝突時要進行辯證。對於困難的東西不能逃避,學習者不論喜歡與否都必須熟練。

─第五講


投資者賺得財富,但秉持良知參與社會,幫那些信任自己的人掙錢。