awk的类sql数据处理
时间:2010-09-02 来源:ztj111
一、先讲讲sql的单表操作,对应awk的单文件处理。
测试环境:sco unix + db2,数据文件名file,数据库表名mytable,为保证准确性,所有语句均做测试。
就以存折明细这样的数据来举例吧,为了实现一些复杂的sql语句,数据有点多。
字段说明:1日期date 2摘要zy 3借贷标志bz 交易金额je 4余额ye 5操作员czy
#cat file 20090106|取款|1|200.00|1770.27|020 |
db2 "select * from mytable" |
sql语句:
select substr(date,1,6),count(*) from mytable where date between '20070101' and '20081231' group by substr(date,1,6) order by substr(date,1,6) |
1 2 |
awk语句:
awk -F "|" '$1>=20070101&&$1<=20081231{a[substr($1,1,6)]++}END{for (i in a) print i,a[i]}' file | sort -k1,1n |
200701 2 |
2、统计07、08年各类交易发生的笔数、金额
sql语句:
select zy,count(*),sum(je) from mx where date between '20070101' and '20081231' group by zy |
ZY 2 3 |
awk语句:
awk -F "|" '$1>=20070101&&$1<=20081231{a[$2]+=$4;b[$2]++}END{for (i in a) print i,b[i],a[i]}' file |
工资 3 1500 |
3、嗯,在我的存折明细中,按月统计下07、08年每个操作员、每月的交易发生笔数吧,扣电费、电话费(czy为auto)的不统计,结果按月份、操作员号排序
sql语句:
select substr(date,1,6)\"月份\",czy,count(*)\"笔数\" from mytable where czy |
月份 CZY 笔数 |
awk语句:
awk -F "|" '$6!="auto"&&substr($1,4,1)~/7|8/{a[substr($1,1,6)" "$6]++}END{for (i in a) print i,a[i]} |
200701 010 1 |
对以上3个例子做个小总结:
awk如何实现sql语句的group分组功能呢?
关键是定义好数组,如:第1例中sql对月份(substr(date,1,6))分组,那awk中就定义数组a[substr($1,1,6)]。至于要给该数组赋怎样的值,看统计需求。如例1统计分组后的次数,就a[substr($1,1,6)]++,表示a[substr($1,1,6)]=a[substr($1,1,6)]+1;若要合计金额,如例2,则a[$2)]+=$4,等价于a[$2]=a[$2]+$4,$4表示第4字段,是金额字段;至于例3,又稍微复杂了点,要根据两个条件分组(月份substr($1,1,6)、操作员$6),那定义的数组就是a[substr($1,1,6)" "$6],注意下标中的" ",是为了输出时显示效果,你也可以改成别的,如改成"#",最后显示效果就是这样:
200701#010 1 |
4、又想到稍微复杂点的,用到了sql语句的having筛选。
统计每年发工资的总额,显示超过750元的年份。
sql语句:
select substr(date,1,4),sum(je) from mytable where zy='工资' group by substr(date,1,4) having sum(je)>750 |
1 2 |
awk语句:
awk -F "|" '$2=="工资"{a[substr($1,1,4)]+=$4}END{for (i in a) if (a[i]>750) print i,a[i]}' file |
2008 800 |
p1:MySco:[/tmp]$db2 "select * from mx" |
p1:MySco:[/tmp]$db2 "select * from khxx" |
对应文件mx.txt和khxx.txt
mx.txt内容如下:
1010001,20070106,存款,400.00,500.00 |
khxx.txt内容如下:
1010001,张三,11111,民主路 |
-------------例子开始-------------
1、统计出2007年1月份发生额总和大于2000的客户,列出帐号、姓名、月份、发生额合计
sql的表关联操作
db2 "select a.acct,a.name,substr(b.date,1,6),sum(b.je) from khxx a,mx b where a.acct=b.acct and substr(b.date,1,6)='200701' group by a.acct,a.name,substr(b.date,1,6) having sum(b.je)>2000" |
awk的处理
awk -F, 'NR==FNR&&substr($2,1,6)=="200701"{a[$1]+=$4}NR>FNR&&a[$1]>2000{print $1,$2,"200701",a[$1]}' mx.txt khxx.txt |
2、统计每个账户2007年1-3月取款业务的发生额总笔数、总金额,列出帐号、户名、摘要、发生额、笔数
db2 "select a.acct,a.name,b.zy,sum(b.je),count(*) from khxx a,mx b where a.acct=b.acct and substr(b.date,1,6) between '200701' and '200703' and b.zy='取款' group by a.acct,a.name,b.zy" |
awk -F, 'NR==FNR&&substr($2,1,6)~/200701|200702|200703/&&$3=="取款"{a[$1]+=$4;b[$1]++}NR>FNR&&$1 in a{print $1,$2,"取款",a[$1],b[$1]}' mx.txt khxx.txt |
就写到这吧,编数据,想例子好累。