# 【教學筆記 01】基礎知識介紹
內容:編碼、檔案、斷行字元、Excel、其他基礎知識介紹
---
[目錄](https://hackmd.io/Y7i9O4hCQu6xOJ94__PhNg)
教學筆記 01:編碼、檔案、斷行字元、Excel、其他基礎知識介紹
[教學筆記 02:Linux 指令介紹 ](https://hackmd.io/9D_WXaT3TsCaBrsOQKYdTw)
[教學筆記 03:awk 指令介紹](https://hackmd.io/PHZRjtQMRi2v9Z-u6bD6Tg)
[教學筆記 04:文件圖表表達方式的經驗分享](https://hackmd.io/xVM9lnFBSneA6uhIzdkYyA)
[教學筆記 05:以 C 語言開發資料庫存取程式 (ECPG)](https://hackmd.io/4jh_5A51TfieovVipQqoXA)
[推薦書籍](https://hackmd.io/t7T5FxfmT3Kih-b7PRUZrA)
[補充教材](https://hackmd.io/w-BNpl_TSuysG4_qaGtmFg)
---
## 一、檔案字元集 (Character Set) 編碼的判斷、轉換
* ### 在台灣常見的編碼,有 ANSI 與 Unicode 兩大體系:
* ANSI:
- [x] ASCII (1 byte) [^ref01] [^ref02]
- [x] BIG5 → MS950 (2 bytes) [^ref03]
- [ ] GB
* Unicode:
- [x] UTF8 (2~3 bytes)
- [x] UTF8 (BOM) (2~3 bytes) [^ref04]
- [ ] UTF16 (LE) (2 bytes)
- [ ] UTF16 (BE) (2 bytes)
- [ ] UTF32 (LE) (2 bytes)
- [ ] UTF32 (BE) (2 bytes)
* ### 判斷編碼的方式:
* 下載範例:[char_set.zip](https://drive.google.com/file/d/1MHGp5G1uVeC55tAkOlBxSwABwN0SvrDN/view?usp=sharing)
* 文字編輯器(Windows記事本、Notepad++...等工具)
* 判斷字元的位元範圍:(利用程式語言、command line)
* There is no 100% reliable way to detemine if a byte stream in ANSI or UTF-8 (without BOM). [^ref05]
* 可利用 Notepad++ 的 HEX-Editor 外掛程式來判斷
* 可利用 Linux 指令來判斷 (於教學筆記 02 再教)
* 中文碼查詢:https://www.cns11643.gov.tw/searchQ.jsp?ID=0
* ### 轉換編碼的方式:
- [x] 記事本另存新檔
- [x] 文字編輯器(notepad++)
- [ ] Linux指令:iconv (於教學筆記 02 再教)
---
## 二、存放資料的檔案 (結構化的文字檔)
* ### 檔案種類:
* 一、以「分隔符號」 (delimiter) 區分欄位:
* 適用於任何字元集編碼
* 較常見
* 常用的分隔符號:逗號(,)、空白、Tab、pipe(|)、ACSII碼(002)
* 亦可同時使用多種字元、字串作為分隔符號
```
1,John,0911-222-333,Taipei City,中華電信總公司
2,May,0922-333-444,New Taipei City,中華電信企業客戶分公司
...
```
* 範例:https://data.gov.tw/dataset/8355 下載 csv 檔,並觀察內容。
* 二、以「固定長度」區分欄位:
* 僅適用於ASCII、BIG5等固定寬度之編碼
* 衍生議題:
* 文字:左靠/右靠
* 數字:左靠/右靠/整數or小數位補幾個0
```
1John0911-222-333 Taipei City中華電信總公司
2 May0922-333-444New Taipei City中華電信企業客戶分公司
...
```
* 範例:[北帳刪帳檔(10107CF.BAD.txt)](https://drive.google.com/file/d/1wcQM10vX2OtqqN3Q0wyTVW8lNaBOmgMF/view?usp=sharing)
* 格式:https://i.imgur.com/gUuQFN8.jpg
* 【練習】各位學員可以嘗試使用 Excel 工具開啟上述兩種檔案,看看會發生什麼問題。
* ### 檔案檢查機制:
檔案有時可能會在傳輸的過程中間遺失資料,因此接收檔案時必須有一些檢查機制。
* 方式一:檔名中包含資料筆數。(例如:FILENAME_YYYYMMDD_筆數.csv)
* 衍生議題:檢查資料筆數與檔名是否相符。
* 方式二:檔案附加尾筆,確認傳輸完畢。(也可以尾筆包含筆數以提供檢查)
* 衍生議題:檢查資料筆數與最後一筆是否相符、去除掉最後一列之後再處理。
```
第 1 筆
第 2 筆
...
第 N 筆
*** N ***
```
* 方式三:利用控制檔,檢查整批檔案的數量、筆數、格式等屬性。
* 財稅案的資料交換規格範例:
* 分為 .H 檔 (資料規格) 與 .D 檔 (資料內容) 兩類檔案
* 未來會用在 oltp -> prestage 之階段
* 範例:VLTT125.20220105.H、VLTT125.20220105.D *<連結已移除>*
* .H檔格式:(佳琪提供)https://i.imgur.com/ny1Yl9w.jpg
---
## 三、斷行字元
* 斷行字元的種類:
| 作業系統種類 | 斷行字元 (※) | 以跳脫序列(escape sequence)方式表示 |
| ------------ | ----------- | -------- |
| WINDOWS | CRLF | \r\n |
| UNIX / Linux | LF | \n |
| MAC | CR | \r |
※ 補充:
| 字元 | 念法 | 跳脫序列 | ASCII碼 (10進位) | ASCII碼 (16進位) |
| ----| --------------- | -------- | --------------- | --------------- |
| CR | Carriage Return | \r | 13 | 0D |
| LF | Line Feed | \n | 10 | 0A |
* 斷行字元的判斷:
* 可利用 Notepad++ 的 HEX-Editor 外掛程式來判斷
* 可利用 PsPad HEX 工具來判斷
* 可利用 Linux 指令 (od) 來判斷
* 【練習】使用一些編輯器,分別在 WINDOWS 或 UNIX 模式下任意編輯,再觀察斷行字元的型態。
* 斷行字元的轉換:
* Notepad++:
* 視窗右下角選擇斷行字元種類。
* 設定 > 偏好設定 > 新文件預設設定 > 切換:Windows/Unix/Mac。
* PsPad:按視窗下方狀態列即可切換。
* 【補充】Linux 指令:
* Windows 轉 Unix (利用 tr、sed、dos2unix 指令)
* Unix 轉 Windows (利用 sed、unix2dos 指令)
* 參考網址:https://www.commandlinewizardry.com/post/removing-windows-line-breaks
---
## 四、Excel 工具
* 工作中時常用來:
* 撰寫文件、圖表
* 比對資料
* 產製具有固定規則的資料
* 常用功能/函式:
* 開啟檔案 (以分隔符號切、以固定長度切)
* 產生數列 (拉控制點 or 公式)
* 判斷資料
* 設定格式化條件
* 樞紐分析表
* 統計圖
* Excel函數線上說明:https://support.microsoft.com/zh-tw/office/excel-%E5%87%BD%E6%95%B8-%E4%BE%9D%E9%A1%9E%E5%88%A5-5f91f4e9-7b42-46d2-9bd1-63f26a86c0eb
* IF
* COUNTIF
* TRIM:移除文字中的 7 位元 ASCII 空格字元 (值 32)。在 Unicode 字元集中,有一個額外的空格字元稱為不分行空格字元,其十進位值為 160。此字元一般用於網頁中,做為 HTML 實體 。單獨使用 TRIM 函數,不會移除此不分行空格字元。
* CLEAN:移除文字中 7 位元 ASCII 碼的前 32 個非列印位元 (值 0 至 31)。在 Unicode 字元集中,還有額外的非列印字元 (值 127、129、141、143、144 及 157)。單獨使用 CLEAN 函數,不會移除這些額外的非列印位元。
* CONCATENATE (功能與 & 相同)
* SUBSTITUTE
* VLOOKUP
* FIND:搜尋文字在另一字串中的起始位置。
* LEFT
* RIGHT
* MID
* AND
* OR
* LEN(X):字串X的長度
* REPT(A,B):字串A重複B次
* CHAR(X):回傳十進位值為X的ASCII code。例如CHAR(65)為"A"。
* CODE(X):回傳ASCII code為X的十進位值。例如CODE("A")為65。
* DEC2HEX(X):將10進位的數字X轉為16進位。
* HEX2DEC(X):將16進位的數字X轉為10進位。
* VBA
---
## 五、de morgan 定理
```
非(P or Q) ≡ (非P) and (非Q)
非(P and Q) ≡ (非P) or (非Q)
```
```
非(P or Q or R) ≡ (非P) and (非Q) and (非R)
非(P and Q and R) ≡ (非P) or (非Q) or (非R)
```

* 舉例:正常人的捐血資格:
1. 17歲以上,65歲以下。
2. 女性應45公斤以上,男性應50公斤以上。
3. 體溫不超過攝氏37.5度。
* 如果一個人可以捐血,就表示:
```
「AGE >= 17歲」 and 「AGE <= 65歲」 and
(「SEX = 女 and WEIGHT >= 45公斤」 or 「SEX = 男 and WEIGHT >= 50公斤」) and
「TEMPERATURE <= 37.5度」
```
* 如果一個人無法捐血,就表示:
```
「AGE < 17歲」 or 「AGE > 65歲」 or
(「SEX = 女 and WEIGHT < 45公斤」 or 「SEX = 男 and WEIGHT < 50公斤」) or
「TEMPERATURE > 37.5度」
```
---
## 作業三:(EXCEL練習)
* SDM下載 (V0.01):FIA_DW_SDM_Base_V0.01_20210128.ods *<連結已移除>*
* SDM下載 (V0.04):FIA_DW_SDM_Base_V0.04_20210222.ods *<連結已移除>*
1. 先將 FIA_DW_SDM_Base_V0.01_20210128.ods 另存為 xlsx 檔,並找出 SDM V0.01 中的「Base基礎資料欄位對應V0_01」頁籤:
(1). 檢查序號是否正確。(不要每一張表都各自拉正確的序號)
※ Hint:正確的序號計算方法:若該列的資料表名稱與上一列相同,則遞增;若不同,則由1起算。
(2). 資料欄位名稱兩側有空白的的欄位有哪些?
2. 先將 FIA_DW_SDM_Base_V0.04_20210222.ods 另存為 xlsx 檔,並利用 SDM V0.04 進行下列工作:
利用資料表名稱、資料欄位名稱、資料型態、不為空值、序號這些資料,製作出下列 CREATE、DROP、INSERT 的 SQL。
(1). 檢查 BASE 表中的序號是否正確。(不要每一張表都各自拉正確的序號)
(2). 對於 STAGE 表進行資料型態的拆解,例如:VARCHAR(X)、DECIMAL(X,Y) ==> 拆出:資料型態(VARCHAR/DECIMAL)、X、Y
產生SQL:
(3). 請利用 BASE 表製作 CREATE TABLE DDL:
| 資料表名稱 | 資料欄位名稱 | 資料型態 | 不為空值 | 序號 | SQL(自建) |
| -------- | ---------- | ------ | ------- | --- | --- |
| table1 | column1 | int | Y |1 |create table base.table1 (column1 int not null, |
| table1 | column2 | varchar(10) | |2 |column2 varchar(10), |
| table1 | column3 | decimal(10,2)| |3 |column3 decimal(10,2)); |
| table2 | column1 | varchar(5) | Y |1 |create table base.table2 (column1 varchar(5) not null, |
| table2 | column2 | text | |2 |column2 text); |
(4). 請利用 BASE 表製作 DROP TABLE DDL:
| 資料表名稱 | 資料欄位名稱 | 資料型態 | 不為空值 | 序號 | SQL(自建) |
| -------- | ---------- | ------ | ------- | --- | --- |
| table1 | column1 | int | Y |1 |drop table base.table1;|
| table1 | column2 | varchar(10) | |2 | |
| table1 | column3 | decimal(10,2)| |3 | |
| table2 | column1 | varchar(5) | Y |1 |drop table base.table2;|
| table2 | column2 | text | |2 | |
(5). 請利用 STAGE 表製作 INSERT SQL:(每張表填一筆資料就好)
規則:依據欄位的資料型態決定欄位的值。
* int:填 1。
* varchar(X)、char(X):填 X 個 'A' (例如:varchar(3) 填 'AAA')。
* text:固定填 'ZZZZZZZZZZ'。
* decimal(X,Y):整數填 X-Y 個 1,小數填 Y 個 1 (例如:decimal(5,2) 填 111.11)。
* decimal(X):整數填 X 個 (例如:decimal(5) 填 11111)。
* date:填 2021-01-01。
* timestamp:填 2021-01-01 00:00:00。
| 資料表名稱 | 資料欄位名稱 | 資料型態 | 不為空值 | 序號 | TYPE(自建) | X(自建) | Y(自建) | SQL(自建) |
| -------- | ---------- | ------ | ------- | --- | ---- | - | - | --- |
| table1 | column1 | int | Y |1 |int | | |insert into base.table1 values (1, |
| table1 | column2 | varchar(10) | |2 |varchar|10| |'AAAAAAAAAA', |
| table1 | column3 | decimal(10,2)| |3 |decimal|10|2|11111111.11); |
| table2 | column1 | varchar(5) | Y |1 |varchar|5 | |insert into base.table2 values ('AAAAA', |
| table2 | column2 | text | |2 |text | | |'ZZZZZZZZZZ'); |
※ 提示: 使用 IF、TRIM、ISERR、FIND、MID、LEN、REPT、OR、&(或CONCATENATE)。
---
## Reference:
[^ref01]: [ASCII](https://zh.wikipedia.org/wiki/ASCII)
[^ref02]: [ASCII Table and Description](http://www.asciitable.com/)
[^ref03]: [代碼頁950](https://zh.wikipedia.org/wiki/%E4%BB%A3%E7%A2%BC%E9%A0%81950)
[^ref04]: [位元組順序記號](https://zh.wikipedia.org/wiki/%E4%BD%8D%E5%85%83%E7%B5%84%E9%A0%86%E5%BA%8F%E8%A8%98%E8%99%9F)
[^ref05]: [How to detect encoding file in ANSI, UTF8 and UTF8 without BOM](https://social.msdn.microsoft.com/Forums/vstudio/de-DE/b172cd4d-25fe-4696-8c0f-37226c053d71/how-to-detect-encoding-file-in-ansi-utf8-and-utf8-without-bom?forum=csharpgeneral)