Tuesday, March 14, 2023

[Oracle] CONNECT BY and Recursive CTE for hierarchy data

  Oracle   CTE   Hierarchy   CONNECT BY

 

▌Problem


Assume that we have a table, EMPLOYEES, which include hierarchy data like this,

 



Each employee has a manager, and a manager also has his/her manager, except JB, who is the boss.

We are going to learn how to use the following 2 ways to traverse the hierarchy rows.

1.  START WITH...CONNECT BY...

2.  Recursive CTE

 

▌START WITH...CONNECT BY...


We can use Oracle's START WITH... CONNECT BY... clause to traverse hierarchal rows.

▋Pattern


SELECT columns
FROM table
START WITH {condition to find the root row}
CONNECT BY {condition to find next row};
\

 

l   START WITH specifies the root row of the hierarchy.

l   CONNECT BY specifies the relationship of parent and child rows.

l   PRIOR indicates the recursive condition to traverse all the rows.
e.q. PRIOR A = B means using current row's column A to match next row's column B. And A = PRIOR B means use current row's column B to match next row's column A.

 

▋SQL

The following SQL lists the top-down hierarchy by starting from JB that has no manager and traverse the records that have manager as JB, and so on.

Notice that the condition to find next row is PRIOR EMP_NO = MANAGER_NO, and that means we use EMP_NO to find(match) the next row by its MANAGER_NO.

 


SELECT EMP_NO, NAME, MANAGER_NO
FROM EMPLOYEES
START WITH MANAGER_NO IS NULL
CONNECT BY PRIOR EMP_NO = MANAGER_NO;

 

Result:



 

And the following SQL lists the bottom-up hierarchy by from James and shows his reporting line.

Notice that the condition to find next row is EMP_NO = PRIOR MANAGER_NO, and that means we use MANAGER_NO to find(match) the next row by its EMP_NO.


SELECT EMP_NO, NAME, MANAGER_NO
FROM EMPLOYEES
START WITH NAME = 'James'
CONNECT BY EMP_NO = PRIOR MANAGER_NO;

 

Result:

 


▌CTE Recursive


We can do the same thing by using CTE recursive.

▋SQL


WITH t1(EMP_NO,NAME,MANAGER_NO) AS
(
    SELECT EMP_NO,NAME,MANAGER_NO FROM EMPLOYEES
    WHERE NAME = 'James'
    UNION ALL
    SELECT t2.EMP_NO, t2.NAME, t2.MANAGER_NO FROM EMPLOYEES t2, t1
    WHERE t2.EMP_NO = t1.MANAGER_NO
)
SELECT * FROM t1;

 

 

Result:

 


▌(Optional) Create a Function


Let's create a Function FindReportLine that returns the report line of an exployee by his/her name.


▋Function by START WITH... CONNECT BY...


CREATE OR REPLACE FUNCTION FindReportLine (
    in_name IN VARCHAR2
) RETURN SYS_REFCURSOR IS
    emp_cursor SYS_REFCURSOR;
BEGIN
    OPEN emp_cursor FOR
    SELECT EMP_NO, NAME, MANAGER_NO
    FROM EMPLOYEES
    START WITH NAME = in_name
    CONNECT BY EMP_NO = PRIOR MANAGER_NO;
    RETURN emp_cursor;
END;


▋Function by Recursive CTE


CREATE OR REPLACE FUNCTION FindReportLine (
    in_name IN VARCHAR2
) RETURN SYS_REFCURSOR IS
    emp_cursor SYS_REFCURSOR;
BEGIN
    OPEN emp_cursor FOR
    WITH t1(emp_no, name, manager_no) as (
        SELECT EMP_NO, NAME, MANAGER_NO
        FROM EMPLOYEES
        WHERE name = in_name
        UNION ALL
        SELECT t2.EMP_NO, t2.name, t2.MANAGER_NO
        FROM EMPLOYEES t2 INNER JOIN t1
        ON t2.EMP_NO = t1.MANAGER_NO
    )
    SELECT * FROM t1;
    RETURN emp_cursor;
END;


▋Use the Function

Since the function returns the rows as SYS_REFCURSOR, we can parse the result by XML.

XMLTABLE maps the result of an XQuery evaluation into relational rows and columns.


SELECT * FROM xmltable(
'/ROWSET/ROW'
PASSING xmltype(FindReportLine('James'))
columns
EMP_NO PATH 'EMP_NO',
NAME PATH 'NAME',
MANAGER_NO PATH 'MANAGER_NO'
);


The XMLSEQUENCE could also do the same thing, though it's deprecated.


SELECT
extractvalue(column_value,'/ROW/EMP_NO') EMP_NO,
extractvalue(column_value,'/ROW/NAME') NAME,
extractvalue(column_value,'/ROW/MANAGER_NO') MANAGER_NO
FROM TABLE(xmlsequence(FindReportLine('James')));


▌(Optional) Aggregate the Result

We can use LISTAGG function in Oracle to combine multiple rows into a single row with each value separated by a specified character or symbol. For example, the following SQL aggregates and show the names of the report line of James.


SELECT LISTAGG(NAME, ' / ') WITHIN GROUP ( ORDER BY ROWNUM ) AS REPORT_LINE
FROM
(
SELECT EMP_NO, NAME, MANAGER_NO
FROM EMPLOYEES
START WITH NAME = 'James'
CONNECT BY EMP_NO = PRIOR MANAGER_NO
);

The result will be "James / Jack / JB".


▌Reference


▋[Sql Server] Recursive CTE for hierarchy data

▋[PostgreSQL] Recursive CTE for hierarchy data

 

 

Sunday, August 7, 2022

[開箱] FILCO Majestouch MINILA-R Convertible

  FILCO   MINILA-R 




 

身為一個碼農,對於鍵盤是有一定的要求度;但是在辦公室很少拿機械式鍵盤,原因是很不習慣聽到別人機械式鍵盤敲打的”機械式”聲音 😡,所以自己自然而然也就不會想用機械式鍵盤去影響別人 😅

 

但是這一年來,陸續接觸了紅軸機械式鍵盤,感覺是個可平衡的選項,聲音不大也有敲打機械式鍵盤獨特的段落感,所以陸續使用了

 

·        ROCCAT Vulcan TKL RGB 紅軸

·        LOGITECH G913 TKL 無線 紅軸

 

ROCCAT雖然是紅軸,但是敲打的聲音還是有清脆的反彈聲,雖然很好聽(跟其他家比起來,個人主觀)也讓輸入的過程非常的爽快,但必須接線又考量到聲音,所以目前拿來當FUN KEYBOARD使用。

而羅技的G913使用上非常滿意,因為短軸的緣故,所以輸入非常輕快和輕鬆,也整合了很直覺的音量調節旋鈕和多功能按鍵,可以切換藍芽和無線連接,而且非常順暢,唯一美中不足的是鍵帽的刻印不明顯,雖然我盲打,但是重點是開啟RGB燈效時,完全沒有FU,只看到鍵盤發光,但完全沒有美感(不過我是早期買的黑色版本,不確定後續是否有改善了),這方面還是ROCCAT比較有娛樂性;因為我在家裡同時必須要連接筆電和桌機,所以目前在家裡就以G913為主囉。

 

回到這篇的主角,也就是因為這一年使用機械式鍵盤的心得,所以就開始物色辦公室用的紅軸鍵盤 XDD

目前放辦公室的LOGITECH CRAFT使用上也非常滿意,但是薄膜式鍵盤的回饋力道比較明顯(快速輸入時,會不自覺的很大力的按到底),在經過連續幾個小時的敲打過程後,會讓我的手指開始產生疲累感,也因為它是100%全幅鍵盤,比較佔空間… 好吧,以上可能都是藉口 XDDD,總之研究了一番之後,決定入手FILCO Majestouch MINILA-R Convertible 60% 鍵盤。

 

我是直接從硬派精靈線上訂再貨到付款,從下訂單到送達門市約三個工作天。

 

接下來就直接上開箱照片了,後面再來說明我自己的60% 鍵盤配置。

 

(包裝盒正面)

 

(內容物)

 

 

 

鍵盤很樸素,也沒有RGB燈效,回歸到本質… 就是鍵位、組合和敲擊。

 

 

打了一天,大概知道為何有FILCO信仰了 😎

雖然是紅軸,但是打擊感除了線性也有扎實感,反彈的力道很Q、很舒服。 對於我自己的重點是因為我手指比較粗,所以我的鍵盤上的按鍵兩兩都必須要有一定的距離,可以看到上圖,它的按鍵是兩層的,對於避免誤觸到兩個鍵非常有幫助,而空白鍵兩旁的組合鍵「FN」,設計上是微凸起的,方便區隔。

當然缺點也是有,就是網路上說的按鍵會有油感,就是看起來和摸起來會有一點”油”的感覺,使用了一天的確看起來好像使用了一個月 XDDD,不過我特地回去看其他黑色鍵盤也是會有,只是沒有那麼明顯,所以也有可能是按鍵顏色的關係會看起來比較有油感,不過不影響輸入。

 

接下來說一下我自己的按鍵配置,這一款60%有配置DIP開關,我打開了1、2、6:

 

DIP

Description

1

將「左ctrl」及「CapsLock」大寫鎖定交換

2

將「左ctrl」及「ESC」交換

6

省電模式

 

在工作上大部分使用 VIM 的按鍵方式,所以在其他鍵盤上,我也是會把原本的「CapsLock」變成「左CTRL」,「左CTRL」改成「ESC」, 這樣我按最左上和最左下都是退出的命令。

這鍵盤由於預設「ESC」是沒有直接輸入的按鍵的,必須要使用「FN」+「~」,這是比較不方便的,不過因為原本的習慣就可以接受改按最左下角位置,只是一開始在按「~」會下意識去找左上第二顆 XDD。

 

另外沒有直接的方向鍵,必須使用以下任一種方式:

1.  搭配「FN」去按「E」「S」「D」「F」

2.  搭配「FN」去按 「?/」、「DEL」、「WIN」、「ALT」

3.  打開DIP開關4: 將右下方的「?/」、「DEL」、「WIN」、「ALT」直接變成「上」「右」「下」「左」方向鍵,但原本的ESDF方向鍵功能將失效,也沒有「?/」

 

我是選擇不打開DIP開關4, 因為「?/」在VIM是常用到的按鍵,所以比較需要花時間習慣的是方向鍵的部分。 如果你是WINDOWS用戶,可以透過 Windows PowerToys去調整按鍵配置。 如下圖我額外把「右CTRL」改成「?/」,上面我啟用的DIP其實也可以直接透過這個軟體來設定即可。

 

 

最後拍一下目前服役中的三個不同廠牌的紅軸鍵盤。

 

 

(更新)使用了兩周後的心得。

優點:

  1. 極佳的鍵盤敲打體驗。聲音很舒服不刺耳。
  2. 60%鍵盤,不占空間。
缺點:
  1. 上面提到打了一陣子後,鍵帽會看起來有一些油油的。
  2. 切換到不同鍵盤的時候,需要重新熟悉一下感覺,尤其是方向鍵。
  3. 方向鍵如果不打開 DIP開關4(右下角模式),因為必須要按著「FN」,所以在一些組合會有點卡,例如切換並選擇當前應用程式(ALT + TAB + 方向鍵)就必須同時用到四隻手指頭。 雖然是可能還不熟練的關係 (這可能熟練嗎 😅)。
其他:
  1. 鍵盤比較高一些些,所以建議買一個中型的鍵盤護墊來搭配使用。
  2. 別人很大機率無法使用你的鍵盤(由於我自己比較注重衛生,所以別人用過我的鍵盤或滑鼠,我會偷偷地用酒精擦拭一下XDDD,不過我通常會放另外一個也連著電腦的鍵盤備用或別人用)

以上是比較針對FILCO Majestouch MINILA-R Convertible的部分。 而以下幾點是使用大部分 60% 鍵盤會需要熟悉的地方

  •  F1 ~ F12鍵必須透過組合鍵觸發(很多開發工具會用到)。
  • 「HOME」和「END」其實還滿常用到的,所以如果有沒有獨立按鍵,也是會有點卡。(我一直以為他們不重要 😅)


(再更新)使用了一個月後的心得。

沒想到放在辦公室使用了一個月多幾天,已經完全適應了 FILCO Majestouch MINILA-R Convertible 60% 鍵盤,反而對家裡的80%鍵盤有點不太適應(尤其是方向鍵會想要先去找FN鍵 😅)。 所以... 又入手了一把茶軸的放家裡使用了 😱😱😱

接下來說一下茶軸的差異:

  1. 敲打音量我覺得可以說是完全沒差異,一樣是很乾淨,是"咚咚"的聲音,不會是那種"鏘鏘"比較尖銳的聲音。
  2. 敲按鍵有一股回饋(反彈)的力道,這是茶軸的特性。雖然力道不大,但是我自己會不自覺多用一點點力氣去敲打,所以個人覺得如果是要長時間快速寫程式或打字,紅軸是比較適合我自己的,但如果你想要有稍微打字機的感覺(就是鍵盤會告訴你... 確實有按下這個鍵的感覺),茶軸就比紅軸適合。 不過話說回來,一切真的都是習慣就好。
  3. 茶軸我是選青藍色(照片可能看不太出來差異),想比之下,灰色鍵盤會比較穩重一點。
最後再補上幾張茶軸的 FILCO Majestouch MINILA-R Convertible。 













Tuesday, July 12, 2022

[markdown] Trivial (冷知識)

 

 

▋Escape special character

 

To escape ` in code snippet, put ` double times and blank before and after a code snippet.  e.q.


`` console.log(`My name is ${name}.`) ``

Notice the format is `` console.log(`My name is ${name}.`) ``

 

▋Center an image


<p align="center">
  <img src="https://xxxx.com.tw/assets/001.jpg" alt="features"/>
</p>


▋Heading Anchors

Here is the example of creating an anchor to a heading in GitHub flavored markdown.



## Heading A

This [link](#heading-b) will go to Heading B.

### Heading B

This [link](#heading-a) will go to Heading A.

 

 

 

 

 

 

Sunday, June 5, 2022

Saturday, June 4, 2022

[Architect] 產品及專案架構設計思維

最近常常被問到,如何為一個產品或專案設計好的架構? 

我回答得很簡短:「首先要了解目的,然後因應當時的環境、時間和資源,評估可以達成這個目的的架構和流程,就是當時最適合的方式。」

然後就會得到



趁著最近比較有空,我把一些自己的想法整理在這篇文章。
但是在更往下之前,我想先談談自己對於 "架構" 這個詞的定義。


架構

我們知道產品和專案都有自己的生命周期。 而我自己心目中的架構是支撐它們可以在各自生命週期運行良好的軟硬體、流程和方法。  例如:

  • 功能開發完成後,團隊可以多久和以多少信心佈署到正式環境?
  • 新進員工加入多久,可以獨立開始作業?
  • 線上有問題時,流程是什麼? 
  • 不同團隊協作流程順暢嗎?
  • 軟硬體架構安全嗎? 有考慮到業務成長量的對應擴充方式嗎?
  • 開發團隊的價值有傳遞給客戶嗎? 我知道客戶在抱怨還是幫我們說話嗎?

所以如果你期望看到底下有軟硬體架構的解決方案,很抱歉並沒有 XDD
這篇文章講得是我個人的思維。


目的

講到"目的",通常我們想到的是:「如期如質上線,滿足老闆或客戶(或BU單位)的需求,讓公司營運正常並賺錢。」

這個大方向沒錯,但是我們再切成 "人"、"系統" 和 "業務" 來看的話,可能就沒有那麼單純。 以系統來看我們要達成的目的, 我們至少必須要知道

  • 分辨必要(Must have)或是次要(Nice to have)的功能。
  • Sizing,未來幾年的業務及系統成長量。
  • SLA, SLO。
  • 如果是專案,專案合約可能有明訂一些必要的規劃和使用的技術。

至於架構設計為何需要考慮到人(即利害關係人)? 原因是每一項任務的成因和老闆的期望,可能不是我們想的那麼單純... 

政治因素、外包廠商、專案價格... etc(還有不好說的那部分),都會影響到我們評估要花多少資源在整個架構及任務上。  或許老闆的期望是讓團隊花更多時間在研發上,那我們就可以花更多資源在設計解決方案上。

業務角度也是重點,產品的業務是以套裝解決方案、或客製化收入為主? 以 SaaS 還是導入客戶端來做為服務重點? 上線後的維運單位和成本? 這會影響到我們的架構設計和技術選型。  


當時的環境、時間和資源

試著回想起三年前或最近剛上線的專案,是不是覺得有更多改善的空間? 肯定是的。
但是當時的情況允許我們用目前更好的架構或方式來建置嗎? 不一定。

考慮環境,包含法規、公司及部門政策和團隊素質。  如果我們的解決方案和架構,和現行環境有衝突的話,就要回過頭去思考目的和思考必要的 tradeoff`。 

至於時間和資源,就不用多說了,鐵定是要考量的因素。 

我自己衡量的標準是

  • 先理解相關利害關係人的期望,在可以完成任務及先滿足擁有權力和資源的關係人(通常是老闆和客戶)的情況下,去嘗試取得更多時間和資源完成團隊的期望。 
  • 透過數據、經驗和知識來下決策,有的時候我們必須要堅持對的事情,去和老闆或客戶持續溝通。
  • 團隊素質如果高的話,可以在過程中去做更多嘗試和想法,這有利於在架構設計上有更多的選擇和彈性。   

當然現實情況是殘忍的,經常不會有最佳的資源去達成我們想要的方式,仍是取捨問題。 


當時最適合

當時最適合的決策和設計,現在回顧可能是錯誤的;也表示我們現在已經成長了也學習到更多經驗和知識,來理解如何用更好的方式來處理它。 隨著資訊越來越進步、技術推陳出新,團隊掌握更多知識和經驗(不管從內部或外部),可以讓我們更快、更準確的於當下做更適合的決策。  我自己的想法是,勇於改變和挑戰,即使結果不如預期,勝於什麼都不想改變。