SQL,在數據處理和分析領域基本上相似「普通話」的地位,幾乎是一項必備的能力,可是要使用 SQL,又離不開關係數據庫系統,也就是 RDBMS,這就比如普通話主要仍是得在中國說才管用。固然,若是爲了去英國美國,學個英語還算值,這就像學個 Python、Hadoop,出去找工做也算是個技能。可是若是要在通常的文本數據,或者 Excel 表格上做分析,就像是去個基里巴斯之類的小國家,爲了可以愉快的購物,難道還要捲起舌頭,從背單詞、學語法開始?這種時候,恐怕第一時間想到的,就是上某寶,淘個好用的翻譯器吧。linux
集算器,在這個問題上,能夠說是一款居家旅行的必備神器了!sql
事實上,用 SQL 處理結構規整的文本或者 Excel 表格數據,除了是一種偷懶的想法外,也是一個很天然的思路。一個文件或者表格由若干數據行構成,而每行數據要麼由肯定的分隔符(空格、逗號、製表符……巴拉巴拉)分隔項目,要麼就是規定了每一個項目的固定長度。這種表示方式,和關係數據庫中的表(Table)幾乎是一模一樣,連變長字段和定長字段也都彷佛有模有樣。不一樣之處,是文件上沒有主鍵、數據類型、是否可空這些概念。另外,就是文件之間關係的說明也沒有像數據庫那樣明確,每每只是做爲業務規則或者經驗,存在於用戶的腦殼裏或者一些給人看的文件裏面。數據庫
集算器的思路,也是如此,經過自動解析結構化文本或者 Excel 文件,將文件映射爲 「表」,並在此基礎上,充分支持 SQL 的語法和功能。windows
好了,閒言少敘,進入正題。咱們以兩個有關聯的文件做爲樣例,看看如何在不「安裝數據庫 -> 建數據庫表 -> 導入數據」的狀況下,輕輕鬆鬆地進行查詢分析:函數
首先,看一下樣例數據,一共是兩個文件:員工信息(employee.txt)和州的基本信息(state.xlsx),注意!這裏咱們使用了兩種文件,一個是格式化的 TXT 文本,另外一個是 Excel 電子表格,也就是說,集算器能夠同時鏈接不一樣類型的數據源,神不神奇?意不意外?工具
更神奇的是,集算器能夠根據文件後綴,自動識別和讀取四種文件類型!分別是:文本(txt)、Excel(xls、xlsx)和 csv 文件。oop
下面兩張圖分別是員工信息和州信息的樣本數據,兩個文件之間經過員工信息中的 STATE 項(第 5 列)和州信息中的 STATEID 項(第 1 列)進行關聯。spa
員工信息數據樣本:操作系統
州信息數據樣本:命令行
好了,立刻開始幹活。首先,最簡單的單表查詢,看看員工中薪酬大於 10000(SALARY>10000)的女(GENDER=’F’)員工,輸出結果按照員工編號(EID)排序,集算器代碼以下:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select * from c:/sql/employee.txt where gender=’F’ and salary>10000 order by eid」) |
沒錯,就這麼簡單,就這麼熟悉!第 1 步,鏈接數據庫……呃,這裏沒有指定參數,因此直接鏈接的就是文件系統,第 2 步,使用 query() 函數執行 SQL 查詢,而這裏的 SQL,除了把 from 後的表名,換成了文件名,別的和數據庫查詢如出一轍!查詢結果以下:
注意,windows 環境下,集算器裏的文件路徑用斜槓「/」而不是反斜槓「\」,這和 Java 語言一致。
好吧,這也太像了,下面咱們來個不太像的,查詢不早於 1980 年 01 月 01 日出生的,薪酬大於 10000 的員工:
A | |
---|---|
1 | $()select * from c:/sql/employee.txt where BIRTHDAY>=date(‘1980-01-01’) and SALARY>10000 |
很簡單,使用 $()至關於 connect() 函數,後面直接寫 SQL 便可。事實上,括號中能夠寫不一樣的數據源名稱,從而同時鏈接多個數據源。
另外,這個例子使用了 SQL 中的字符串轉日期的函數 date()。
接下來,是 SQL 數據庫有別於單個文件的關鍵,關聯查詢。對於薪酬大於 10000 的女員工,還想再看看她們都在哪一個州:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select t1.eid eid,t1.name name,t1.gender gender,t2.name state,t2.population population,t1.salary salary from c:/sql/employee.txt t1 left join c:/sql/state.xlsx t2 on t1.state=t2.stateid where t1.gender=’F’ and t1.salary>10000 「) |
嗯,用文件名代替表名確實有點長,因此咱們用了 SQL 中別名的用法,結果以下:
除了使用別名代替文件的絕對路徑,對於特別長的路徑或者文件不少的狀況,爲了方便書寫和清晰閱讀,還能夠在集算器 - 菜單 - 工具 - 選項中配置主目錄,這樣就能夠在 SQL 中直接使用文件名或者相對路徑了。這是否是更像指定了一個數據庫,直接訪問其中的表了?
配置方法以下圖所示:
配置了主目錄後的查詢是這個樣子,查詢工資總額大於 100000 的部門對應的人數和工資總額:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select dept,count(1) c,sum(salary) s from employee.txt group by dept having s>100000」) |
查詢結果以下:
下面,進入一些細節內容:
1)集算器支持邏輯運算 and、or 和 not,例如:查詢員工姓 Smith 或者 Robinson,而且是 Sales 部門以外的男員工:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select * from employee.txt where (surname=’Smith’ or surname=’Robinson’) and gender=’M’ and not dept=’Sales’ 「) |
2)集算器中,支持用 is null 來判斷是否爲空,用 is not null 判斷非空,例如:找出 surname 爲空的員工:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select EID,NAME,SURNAME from employee.txt where surname is null」) |
同時支持用 coalesce 函數處理空值,例如:員工 surname 字段爲空時在結果中顯示爲「UNKNOWN」:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select EID,NAME,SURNAME,coalesce(SURNAME,’UNKNOWN’) as SURNAME1 from employee.txt」) |
查詢結果爲:
注意:集算器中的字段別名,不能和文件中的字段名重複。
3)集算器支持 Case when,例如:性別字段爲「F」的要顯示爲「female」,爲「M」的要顯示爲「male」。
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select EID,NAME,GENDER,(case gender when ‘F’ then ‘female’ else ‘male’ end) as GENDER1 from employee.txt」) |
查詢結果爲:
4)集算器支持 like 關鍵字進行模糊查詢,例如:在員工中,查詢 surname 字段包含「son」的員工。
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select * from employee.txt where surname like ‘%son%’」) |
其中的「%」爲通配符,表示一個或者多個字符。另外,「_」表示一個字符。若是要查詢以「son」結尾,而且前面有三個字符的狀況,能夠寫成 surname like ‘___son’;「[WJ]」表示包含「W」和「J」的字符列表。surname like ‘[WJ]%’表示 surname 是以「W」或者「J」開頭。surname like ‘[!WJ]%’表示 surname 不是以「W」或者「J」開頭。
5)集算器支持經過 In 關鍵字在多個值中查詢數據。例如:查詢「Finance、Sales、R&D」三個部門的員工。
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select * from employee.txt where dept in (‘Finance’,’Sales’,’R&D’) 「) |
6)集算器支持經過 with T as (x) 的方式定義一個外部表。例如:employee.txt 中的 state 字段和另外一個數據源 demo 數據庫的 state 表的 stateid 字段左鏈接,查出每一個員工所在州的名字和人口:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「with t2 as (connect(\」demo\」).query(\」select * from states\」)) select t1.eid eid,t1.name name,t1.gender gender,t2.name state,t2.population population,t1.salary salary from employee.txt t1 left join t2 on t1.STATE=t2.STATEID」) |
在這個 SQL 中:
with t2 as (connect(\」demo\」).query(\」select from states\」)) 定義了一個外部表 t2,鏈接 demo 數據源(其實是集算器自帶的 hsql 演示數據庫),用 query 函數執行 SQL「select from states」。(其中,\」是在字符串中使用雙引號的轉義寫法)
後邊的「select t1.eid … left join t2 on t1.STATE=t2.STATEID」則利用定義好的 t2 和 employee.txt 左鏈接,查出每一個員工所在州的名字和人口。
這個查詢是典型的數據庫和文本文件的聯合查詢。實際上,with 關鍵字能夠定義各類數據源查出的數據,從而很是靈活的實現跨異構數據源的聯合查詢。
7)集算器支持經過 into to 將查詢結果輸出的文件中。例如:查詢工資總額大於 100000 的部門對應的人數和工資總額,結果寫入 deptResult.xlsx。這裏,新的文件就相似關係數據數據庫裏的一個新表。
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select dept,count(1) c,sum(salary) s into deptResult.xlsx from employee.txt group by dept having s>100000」) |
說了這麼多,能夠看出,經過集算器,咱們就可以基本實如今結構化的文本數據(txt、csv 等)和 Excel 文件(xls、xlsx)上輕鬆、直接地使用 SQL。
固然,集算器並非徹底「平移」複製了 SQL 的能力,對於 SQL 中的子查詢,集算器目前並不能直接支持,而是會以更加靈活、方便、直觀的分步式計算方式加以解決。同時,對於有些特殊的 join 計算,集算器和傳統數據庫相比會慢一點。
最後,咱們再來看看經過集算器進行 SQL 計算,還能額外得到哪些福利:
1)根據輸入參數動態計算:
在進行數據查詢時,經常須要根據不一樣的條件進行計算,也就是咱們說的動態執行。這時,咱們能夠定義「網格參數」,爲可能發生變化的條件預留位置。例如:想要找出公司裏較高薪水的年輕員工有哪些,可是年齡段和薪酬起始線還不肯定,咱們就能夠在集算器 IDE 的菜單「程序 / 網格參數」中,定義兩個參數:birthday 和 salary:
而後在查詢語句中用佔位符「?」寫出 SQL,並按順序指定對應的網格參數名做爲輸入:
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select * from employee.txt where BIRTHDAY>=? and SALARY>?」,birthday,salary) |
若是在定義網格參數的時候指定了具體的數值,而且沒有勾選「每次運行前設置參數」那麼運行腳步會直接指定的數值。若是勾選了「每次運行前設置參數」,那麼每次運行腳本的時候,都會彈出「設置參數值」窗口。這樣,咱們就能夠隨時輸入咱們須要的參數值了,相應地,查詢結果也會隨之改變了:
2)在命令行中使用 SQL 查詢文件
在 windows 或者 linux 系統中,咱們還能夠經過命令行中調用編寫好的集算器腳本,直接對文件數據進行查詢。若是結合操做系統的定時任務機制,就能夠在指定時間完成批量數據計算了。
咱們先看一個不返回結果集的例子。按期爲財務部門提供工資總額大於 100000 的部門對應的人數和工資總額,結果寫入 deptResult.xlsx(而後能夠經過郵件或其餘方式發送給相關人員)。
首先,編寫集算器腳本,並保存爲 deptResult.dfx。
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select dept,count(1) c,sum(salary) s into deptResult.xlsx from employee.txt group by dept having s>100000」) |
3 | >output(「create deptResult.xlsx successfully!」) |
而後,在命令行執行 esprocx.exe 命令,(在集算器安裝目錄的 bin 文件夾中),執行結果:
| C:\Program Files\raqsoft\esProc\bin>esprocx.exe deptResult.dfxcreate deptResult.xlsx successfully! |
其中,第二行是 Output 函數輸出的提示信息,能夠用於監控程序執行和調試。
咱們再看一個返回結果集的例子,一樣的查詢需求,可是不要求輸出到文件中,而是直接查看結果。此次咱們把編寫的集算器腳本換個名字存爲 deptQuery.dfx。
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select dept,count(1) c,sum(salary) s from employee.txt group by dept having s>100000」) |
3 | return A2 |
在命令行中的執行並查看結果:
更進一步,集算器也能夠作到直接在命令行寫完整的 SQL 語句,直接從文件中返回須要查詢的結果。是否是和數據庫命令行查詢工具同樣方便?
先定義一個參數 sql,用來傳入須要查詢的 SQL 語句。
而後編寫以下集算器腳本,保存爲 query.dfx,
A | |
---|---|
1 | =connect() |
2 | =A1.query(sql) |
3 | return A2 |
執行命令時,在命令行中直接寫 SQL 語句,結果以下:
結合前面說的根據參數動態計算的方法,也能夠在使用命令行計算時實現必定的交互。仍是之前面說過的查詢公司裏薪酬較高的年輕員工爲例:
在集算器 IDE 菜單「程序 / 網格參數」中,定義兩個參數:birthday 和 salary。
編寫以下集算器腳本,保存爲 empQueryParam.dfx,
A | |
---|---|
1 | =connect() |
2 | =A1.query(「select * from employee.txt where BIRTHDAY>=? and SALARY>?」,birthday,salary) |
3 | return A2 |
執行命令時,按照順序爲兩個參數提供數值,結果以下:
至此,咱們已經充分了解了利用集算器,就能夠用 SQL 這把「金剛鑽」來攬數據文件這些「瓷器活兒」了。其實,這個故事裏,集算器纔是真正的「金剛鑽」!除了本文描述的將數據文件直接做爲「表」來處理的方式,集算器真正有力的武器庫遠不止此。經過這款輕量級的數據分析工具,不管是數據庫仍是文件系統中的數據,均可以被輕鬆處理,快刀斬亂麻!