Chinaunix首页 | 论坛 | 博客

-

  • 博客访问: 4134486
  • 博文数量: 172
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1923
  • 用 户 组: 普通用户
  • 注册时间: 2018-12-20 14:57
文章分类
文章存档

2021年(19)

2020年(81)

2019年(68)

2018年(4)

我的朋友

分类: 敏捷开发

2020-10-21 14:30:05

因为支持文件计算、性能优化等独特功能,esProc的SQL功能深受大家喜爱,为了大家更方便地使用,下面将总结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,且点击不同的单元格可直接在右边查看计算结果。下面是一些例子:

imagepng


具体SQL写法不是本文重点,若感兴趣可参考 [在文件上使用 SQL 查询的示例]()

在命令行执行SQL

不方便使用图形环境时,可以在命令行执行SQL。Windows下应使用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函数可以读取格式更复杂的文件,详细用法参考

为了更直观地使用列名,可以先改列名再计算。传统的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函数可参考

跳过空行

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

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

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

代码中第二个select是SPL的查询函数,select(#1)表示第1个字段不为空。可以用该函数筛选更复杂的数据行,而不仅仅是空行。函数select参考

如果首行数据无效,就不能用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函数可将字符串转为二维表。

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

$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中实现不同数据源之间的混合计算。

比如Oracle的sales表存放员工的销售订单,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'

 

阅读(48236) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~