两种检查数据重复性的方法

6 篇文章 0 订阅
6 篇文章 0 订阅

 

我们在ETL测试过程中经常甚至是必须要检测某一批数据中的某些维度在表范围内是否重复。

 

本文就介绍两种检测数据重复的简单方法。

 

方法1

SQL

如果这些数据在数据库中,那完全简单而且OK。具体方法为:

 

select (sum(c)-count(c)) uniq
from (
    select count(1) c
    from   table_t
    group by col1,col2,....coln
) a

 如果结果为0,则说明对应的维度上满足唯一性要求。

 

方法2:

Linux命令法

有时候,我们得到一个体积较大的数据文件(从数据仓库导出做别用),想要检查这个文件中的某些个字段维度上是否满足唯一性要求。当然,我们可以将这个文件导回到数据库,然后再写上面的SQL语句搞定。但是这样做难免小题大作了。因为,我们的需求很简单,而且由于数据文件较大,搞到数据库里对存储、计算、资源维护都是一种浪费。

 

现在分量中情况处理:

(1)数据待检查维度上有序:

我们可以通过如下命令来解决这个问题:

 

cut -d "[分隔符]" -f [你需要的维度] [你的数据文件] | uniq -c | grep -v -e '^ \+1 ' | wc -l

 

上面的方法,采用最粗暴的遍历文件方法搞定,同样也是最简单的,比其导入数据库,分配额外存储空间,建立索引,SQL查询计算等来讲简直是太简单了。

 

而且单从SQL与linux command执行效率来讲,SQL中的group by效率不见得比Linux command高。

 

如果我们需要统计所有维度上有无重复数据,则更简便,方法为:

 

 

uniq -c [你的数据文件] | grep -v -e '^ \+1 ' | wc -l

 

一个实际示例:

一个千万级的数据文件进行维度唯一性检查时,在我的台式机上安装的虚拟机上(哈哈,性能够差的)执行大概需要10秒左右的样子。

 

(2)数据待检查维度上无序:

面对这样的数据,uniq要想发挥作用,则必须在uniq之前进行sort,而对于大数据来讲sort是不可行的。

因为无论如何sort也需要nlogn的时间复杂度才能OK,而接着uniq也需要n的复杂度。而且,sort需要将全部数据读入内存。

 

由于数据无序,此时最优的方法就是扫描一遍数据得出结果。这需要借助我们上一篇博文中介绍的awk的方法完成,不过我们不需要计算sum值。

 

代码稍作修改,count.awk 文件如下:

 

 

BEGIN{
}
{
    if($0 in count){
        count[$0]+=1;
    }
    else{
        count[$0] =1;
    }
}
END{
    for(x in count){
        print count[x]:"x";
    }
}

 

此时,借助count.awk的功能,实现方案为:

 

 

grep -v -e '^$' [你的文件] | cut -d "[分隔符]" -f [维度] | awk -f count.awk | grep -v -e '^1:' | wc -l

 

首先去除空行,然后选取需要检查的维度,传入count.awk文件中统计维度上数据出现的次数,最后计算出现不止一次的数据又多少个。

 

如果结果为0,则说明检查维度上数据唯一,否则不唯一。

 

 

例如,一个文件为:

a,b,c

a,c,e

a,b,e

a,c,f

a,d,g

a,e,g

 

运行上述命令检查前两个维度上是否有重复,结果为:

2   --a,b和a,c分别都出现了两次。

 

如果检查全部维度上的唯一性,则上述命令中的 [cut] 部分就可以不用了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要避免在使用SqlBulkCopy插入数据时出现重复数据,可以考虑以下两种方法: 1. 在插入之前先检查是否存在重复数据,如果存在则不进行插入。可以通过在目标表中设置唯一性约束或者创建临时表并在其中进行检查来实现。 2. 在SqlBulkCopy的WriteToServer方法中使用SqlBulkCopyOptions中的KeepIdentity选项,以保留目标表中已有的自增长主键,从而避免插入重复的自增长主键。 以下是使用第一种方法的示例代码: ```csharp using System.Data.SqlClient; using System.Data; //创建一个DataTable对象,用于存储要插入的数据 DataTable dt = new DataTable(); //添加列 dt.Columns.Add("Name", typeof(string)); dt.Columns.Add("Age", typeof(int)); //添加数据 dt.Rows.Add("John", 25); dt.Rows.Add("Mike", 30); //创建连接对象 SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=TestDB;Integrated Security=True;"); //打开连接 conn.Open(); //创建事务对象 SqlTransaction tran = conn.BeginTransaction(); try { //创建SqlBulkCopy对象 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, tran)) { //设置目标表名 bulkCopy.DestinationTableName = "Person"; //设置列映射 bulkCopy.ColumnMappings.Add("Name", "Name"); bulkCopy.ColumnMappings.Add("Age", "Age"); //使用SqlBulkCopyOptions中的CheckConstraints选项检查唯一性约束 bulkCopy.WriteToServer(dt, SqlBulkCopyOptions.CheckConstraints); } //提交事务 tran.Commit(); } catch (Exception ex) { //回滚事务 tran.Rollback(); throw ex; } finally { //关闭连接 conn.Close(); } ``` 使用第二种方法时,只需要在SqlBulkCopy的构造函数中指定KeepIdentity选项即可: ```csharp using System.Data.SqlClient; using System.Data; //创建一个DataTable对象,用于存储要插入的数据 DataTable dt = new DataTable(); //添加列 dt.Columns.Add("Name", typeof(string)); dt.Columns.Add("Age", typeof(int)); //添加数据 dt.Rows.Add("John", 25); dt.Rows.Add("Mike", 30); //创建连接对象 SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=TestDB;Integrated Security=True;"); //打开连接 conn.Open(); //创建事务对象 SqlTransaction tran = conn.BeginTransaction(); try { //创建SqlBulkCopy对象,并设置KeepIdentity选项 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn, SqlBulkCopyOptions.KeepIdentity, tran)) { //设置目标表名 bulkCopy.DestinationTableName = "Person"; //设置列映射 bulkCopy.ColumnMappings.Add("Name", "Name"); bulkCopy.ColumnMappings.Add("Age", "Age"); bulkCopy.WriteToServer(dt); } //提交事务 tran.Commit(); } catch (Exception ex) { //回滚事务 tran.Rollback(); throw ex; } finally { //关闭连接 conn.Close(); } ``` 以上示例代码仅供参考,实际应用中需要根据具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值