关于 awk 用于 sql 脚本拼写的数据去重处理

  |   0 评论   |   2,721 浏览

由于数据库表设计初期考虑欠佳,经常出现数据重复的情况.因此需要删除其中的重复数据,然后对数据库表添加唯一索引从而从表设计上避免重复数据产生.这里举例的场景纯属虚构.主要是为了说明 awk 的这一使用方法.

数据

考虑如下数据

数据 ID用户名(userName)订单号 (orderNo)评论 (comment)
1张三10100001途家民宿体验不错
2李四10100002第一次住途家民宿
3李四10100003第二次入住途家民宿,体验还是一如既往的好!
4李四10100003第二次入住途家民宿,体验还是一如既往的好!
5乔峰10100008这次来中原,第一次体验途家民宿,非常适合江湖人士!
6乔峰10100008这次来中原,第一次体验途家民宿,非常适合江湖人士!

如下,假设一个订单一个入住人只能评论一次, 这里由于设计缺陷,导致数据重复;这里需要把重复数据筛选出来.并生成相应的删除 SQL.

假设有重复的数据已经生成,并放到了一个 txt 文件中.第一反应可以使用 sortuniq 等相应的命令来完成此去重.但是实际使用场景都不太匹配.

awk命令的命令模型(参考:shell-awk)为 模式 + {行为(Action)}

awk的程序指令由模式和操作组成,即Pattern { Action }的形式,如果省略Action,则默认执行 print $0 的操作.
因此,借助此特性,只要能够识别一行数据在流式处理时,前面是否已经出现过.就可以决定是打印此行,还是不打印此行;

实现去除重复功能的就是这里的Pattern:bash!a[$0]++; 在awk中,对于未初始化的数组变量,在进行数值运算的时候,会赋予初值0,因此a[$0]=0,++运算符的特性是先取值,后加1,因此Pattern等价于:!0,这个 Pattern 的意思就是如果$0没有出现过,就打印此行的值(没有写 Action 的时候默认是打印整行!);

针对此场景: 需要反过来,第一次出现的略过,不进行处理.第二次以上出现的需要输出一行删除此数据的 sql; 这里进行两个小改动:

  • $0修改为需要判定唯一性的字符串,这里需要进行字符串拼接:$3"-"$4,用这个联合唯一索引进行去重.然后再重写action部分:

处理过程

源数据:

| 1 |  张三  | 10100001 | [途家](http://www.tujia.com)民宿体验不错 |
| 2 |  李四  | 10100002 | 第一次住途家民宿  |
| 3 |  李四  | 10100003 |第二次入住途家民宿,体验还是一如既往的好!  |
| 4 |  李四  | 10100003 |第二次入住途家民宿,体验还是一如既往的好!  |
| 5 |  乔峰  | 10100008 |这次来中原,第一次体验途家民宿,非常适合江湖人士!  |
| 6 |  乔峰  | 10100008 |这次来中原,第一次体验途家民宿,非常适合江湖人士!  |

脚本:

[macbook@localhost ~/Desktop]$cat test.txt | awk -F"|" 'a[$3"-"$4]++'
| 4 |  李四  | 10100003 |第二次入住途家民宿,体验还是一如既往的好!  |
| 6 |  乔峰  | 10100008 |这次来中原,第一次体验途家民宿,非常适合江湖人士!  |

拼 SQL:

[macbook@localhost ~/Desktop]$cat test.txt | awk -F"|" 'a[$3"-"$4]++ {print "delete from xxx where id ="$2";"}'
delete from xxx where id = 4 ;
delete from xxx where id = 6 ;

本文处理参考了如下文章:

[1] Linux命令去重统计排序
[2] awk 中各种模式详解

评论

发表评论


取消