esProc 的 SQL 应用方案

esProc 的 SQL 功能支持文件计算、性能优化等独特功能,本文将总结桌面 IDE、命令行等不同环境下 SQL 的用法,以及常用文件格式、特殊分隔符等多种应用方案,详情点击esProc 的 SQL 应用方案

因为支持文件计算、性能优化等独特功能,esProcSQL功能深受大家喜爱,为了大家更方便地使用,下面将总结SQL的各类应用方案。

基本用法

SQL的基本数据源为文本文件和Excel。文本文件有两种常见的分隔符,制表符分隔的文件一般以txt为扩展名,逗号分隔的文件通常以csv为扩展名,esProc可凭借扩展名自动识别。Excel有两种不同的版本,格式较旧的xls文件和格式较新的xlsx文件,esProc同样可凭扩展名自动识别。

SQL的基本数据格式为带列名的二维表,比如下面的sales.txt

OrderID                Client    SellerId Amount               OrderDate

26           TAS        1              2142.4   2009-08-05

33           DSGC     1              613.2     2009-08-14

84           GC          1              88.5        2009-10-16

 

SQL的基本运行环境为网格脚本,在windows/linux下均可使用。在网格脚本中,可以编写/维护/执行多个SQL,且点击不同的单元格可直接在右边查看计算结果。下面是一些例子:


具体SQL写法不是本文重点,若感兴趣可参考 [在文件上使用 SQL 查询的示例](https://c.raqsoft.com.cn/article/1600073770278)

在命令行执行SQL

不方便使用图形环境时,可以在命令行执行SQLWindows下应使用esprocx.exe命令,例如:

esprocx.exe -r select * from Order.txt

需要注意的是,SQL IDE中必须使用前导符号$,而命令行中可以省略该符号。

Linux环境下应使用esprocx.sh 命令,例如:

./esprocx.sh -r select * from Order.txt

无列名的情况

有些文件没有列名(列标题),则可以将SPL语句嵌入SQL,利用SPL的能力灵活处理列名。比如sOrderNT.txt部分数据如下:

26           TAS        1              2142.4   2009-08-05

33           DSGC     1              613.2     2009-08-14

84           GC          1              88.5        2009-10-16

133         HU          1              1419.8   2010-12-12

按第2列查询时,SQL应写作:

$select *   from {file("sOrderNT.txt").import()} where _2='TAS'

SQL中可以看到,数据无列名时,则以"下划线+序号"为默认列名,第2列的列名就用_2表示,其他列以此类推。{}内是SPL语言,其中import函数可以读取格式更复杂的文件,详细用法参考http://doc.raqsoft.com/esproc/func/fimport.html

为了更直观地使用列名,可以先改列名再计算。传统的SQL写法是用子查询改列名,上面的SQL可改为:

$select * from (

        select _1 OrderID ,_2   Client, _3 SellerId, _4 Amount, _5 OrderDate from   {file("sOrderNT.txt").import()})

where Client='TAS'

传统的子查询效率不高且阅读不便,使用SPL语句可以避免子查询,同时可以达到修改列名的目的:

$select * from

{file("sOrderNT.txt").import().rename(_1:OrderID,   _2:Client, _3:SellerId, _4:Amount, _5:OrderDate)}

where Client='TAS'

 

特殊分隔符

有些文件的分隔符不是常见的制表符或逗号,而是分号冒号等特殊符号,有时甚至用多个字符当分隔符,这种情况下应该用SPL语句中的import函数来指定分隔符。

比如sep.txt的分隔符是双线||,则可以用下面的SQL来读取:

$select * from   {file("sep.txt").import@t(;,"||")}


无换行符

有些文件没有用回车换行区分记录,而是用其他符号,这样的文件整体呈现为一个大字符串。比如SOrderNL.txt的记录之间用|符号分隔:

OrderID                Client    SellerId Amount               OrderDate|26   TAS        1              2142.4   2009-08-05|33                DSGC     1              613.2     2009-08-14…

这种情况要把文件读为字符串,将|替换成回车换行,再用import函数解析为二维表。

$select * from   {replace(file("sOrderNL.txt").read(),"|","\r\n").import@t()}

read函数可参考http://doc.raqsoft.com/esproc/func/read.html

跳过空行

有些文件存在空行,需要跳过才能使用。处理这种情况的一般思路是:在SQL中嵌入SPL语句,用SPL语句读入文件,查询出有用的数据行。

最简单的情况是首行数据有效(可以用import函数解析成二维表),而首行之后不定的位置存在空行。这样文件可用以下SQL查询:

$select * from {file("sOrderb.txt").import@t().select(#1)}

代码中第二个selectSPL的查询函数,select(#1)表示第1个字段不为空。可以用该函数筛选更复杂的数据行,而不仅仅是空行。函数select参考http://doc.raqsoft.com/esproc/func/select.html

如果首行数据无效,就不能用import函数解析成二维表了,这种情况下要用read函数读成行数据,找到有效数据后,再转为二维表。比如前3行无效,正式数据从第4行开始,SQL代码为:

$select * from {file("sOrderb.txt").read@n().to(4:).concat("\r\n").import@t()}

代码中to(4:)表示取第4行直到结尾,即有效数据。concat("\r\n")表示将多行数据拼成一个大字符串,行之间用回车换行符连接。Import函数可将字符串转为二维表。

更复杂的情况下,文件在任意位置都可能存在空行,这时要用SPLselect函数进行一般查询,代码如下:

$select * from {file("sOrderb.txt").read@n().select(~!="").concat("\r\n").import@t()}   where Client='TAS'

 

数据源为SPL 中间计算结果

从前面例子可以看出,有些文件不够规范,需要用较长的SPL代码去解析文件。SPL代码太长,就无法利用网格代码的优势,不仅影响阅读代码,且不方便查错改错。为了充分利用网格代码的优势,esProc SQL允许将任意的SPL中间计算结果作为数据源。

比如“文件在任意位置都可能存在空行”这个例子,可以改用下面的代码:


A

B

1

=file("sOrderb.txt").read@n()

/按行读入文件

2

=A1.select(~!="")

/取非空行

3

=A2.concat("\r\n").import@t()

/合并为大字符串,解析为二维表

4

$select * from {A3}   where Client='TAS'

/SPL为源执行SQL

任意的SPL中间结果都可以作为SQL的数据源,这就给SQL语句提供了无限的可能性,包括复杂的文件解析、特殊数据源、大文件计算、循环判断、多源混算等等。

 

数据源为Excel 粘贴而来的数据

Excel文件当数据源是SQL 的基本用法,也可以利用SPL,把Excel粘贴而来的数据当做数据源。

比如Excel存储着学生成绩,如下图:


A

B

C

D

1

name

math

english

physics

2

lily

97

100

99

3

Joshua

100

99

100

4

Sarah

98

99

96

5

Bertram

94

95

85

6

Paula

91

88

91

7

Sophia

92

81

76

8

Ben

87

80

76

9

Ruth

92

91

87

10

Pag

95

87

87

首先在Excel中选定A1:D10,连带列名一起复制粘贴到esProc脚本的A1单元格,再编写SPL代码,最后编写SQL。如下图:


A

B

1

name math english   physics lily 97 100 99 Joshua 100 99 100…

/Excel粘贴来的数据

2

=A1.import@t()

/解析为二维表

3

$select * from {A2}  where math>=80

/执行SQL

注意,一定要进入A1格的编辑状态才能进行复制,不然会把剪贴板的内容填进一大片格子,虽然也有办法进行计算,但占有区域太大,会影响代码布局。

多行记录

多行记录属于格式不规范的文件,比如下面的文件每三行代表一条记录,第一条记录是:26\TAS\1\2142.4\2009-08-05

26

TAS        1              2142.4

2009-08-05

33

DSGC     1              613.2

2009-08-14

84

GC          1              88.5

2009-10-16

下面使用SPL将该文件整理成规范二维表,再用作SQL数据源,代码如下:


A

B

1

=file("D:\\data.txt").import@si()

将文件读为序列,不拆分字段

2

=A1.group((#-1)\3)

3行分一组

3

=A2.new(~(1):OrderID,   (line=~(2).array("\t"))(1):Client,line(2):SellerId,line(3):Amount,~(3):OrderDate   )

创建二维表,~(1)表示当前组的第1个成员

4

$select * from {A3} where year(OrderData)=2009


 

多源混算

利用SPL语言,可以在SQL中实现不同数据源之间的混合计算。

比如Oraclesales表存放员工的销售订单,excel文件emp.xlsx存放各部门的员工信息,需要计算每个部门的销售额,可使用如下代码:

 


A

B

1

=file("emp.xlsx").xlsimport@t()

/Excel 数据源

2

=connect("orcl").query@x("select   * from sales")

/数据库数据源

3

$select   e.dept,sum(s.amount) from {A2} s left join {A1} e on s.sellerid=e.eid group   by e.dept

/混合计算

 

高性能文件格式

如果文件较大,SQL性能较差,可转为esProc高性能文件格式btx。比如将orders.txt转为orders.btx,代码如下:


A

B

1

=file("orders.txt").cursor@t()

/游标方式打开大文本文件

2

=A1.sortx(OrderID)

/排序

2

=file("sales.btx").export@z(A2)

/转为btx格式,@z表示文件有序

btx的基本用法与文本文件和Excel一样,但性能会显著提升,比如条件查询:

$select     orderid,client,amount from sales.btx where Client='TAS'

 

Txtbtx的差异可参考http://doc.raqsoft.com/esproc/tutorial/jiwenjian.html   

如果想进一步提高SQL性能,就要使用更高性能的ctx文件以及esProc扩展的SQL+能力了,可以提供包括并行计算等能力,参考:http://doc.raqsoft.com/esproc/func/sqljia.html