2.9 随机抽样
在审计或IT审计中,常常使用抽样,也就是对具有审计相关性的总体中低于百分之百的项目实施审计程序,使所有抽样单元都有被选取的机会,为注册会计师针对整个总体得出结论提供合理基础。简单来说,就是我们需要从总体中选出一些样本,通过对样本的检查,得出结论,再推导出总体的结论。
在Excel中或一些软件中,我们可以非常容易在数据中抽样,但当数据量超过Excel表最大限制时或数据很大时,我们需要在数据库中处理,那么如何用SQL抽样,就是我们应该掌握的。本节我们介绍随机抽样的三种方法,数据仍采用2.6节中APP数据集里AppleStore表作为讲解示例。首先,我们通过select count(*) from AppleStore
求出表中有7142条数据,假设我们需要随机抽样出100条数据。
「方法一」
select * from AppleStoreorder by rand()limit 100;
解释:rand()
函数会产生0-1之间的随机数,order by rand()
根据产生的随机数进行排序。limit 100
截取前100行数据。从而达到随机抽样100条数据的目的。当然如果需要抽样出N条数据就使用limit N
。即:
select * from 表名order by rand()limit N;
需要注意的是,虽然这是最简单的方法,并且在数据较小的表执行速度较快,但是当数据较大的时候,查询速度就会较慢。
「方法二」
我们先计算我们需要抽样数据与总体的占比100/7142=0.014
,然后通过查询语句随机抽样出上述比例的数据:
select * from AppleStorewhere rand()<0.014
解释:对于每一行数据,都会执行判断条件where rand()<0.014
,而rand()
是产生0-1的随机函数,那么每条数据都有0.014的机率被筛选出来,最终会筛选出总体×0.014
条数据。当然实际筛选出的数据条数不是固定的,它随着数据量越大越接近0.014这个比例。我们为了抽取出刚好100条数据,我们可以稍微提高抽取的比例,然后使用limit 100
截取前100条数据:
select * from AppleStorewhere rand()<0.015limit 100;
「方法三」
本方法需要表中有一列是连续编号的数字,一般的表中id或序号都是连续编号的,我们可以直接使用。如果没有连续编号的列,那么我们需要人为的创建一列序号数据。在AppleStore中无论是id还是序号都是不连续的,所以我们首先新增一列,列名为‘num’。
新增列语法:
alter table 表名 add column 列名 数据类型;
比如,给AppleStore新增一列num,数据类型为int:
alter table AppleStore add column num int;
删除列语法:
alter table 表名 drop column 列名;
修改列名语法:
alter table 表名 change 原列名 新列名 数据类型;
以上是对列操作的语句用法,下面我们给创建的num列添加连续的序号:
set @rn=0;update AppleStore set num=(@rn:=@rn+1);
解释:在SQL中命名一个变量需要在前面加一个@符号,这里我们命名一个代表行数的变量@rn
(row number)。update 表名 set 列名=值 where 列名=某值
是修改值的语法。这里我们用num=(@rn:=@rn+1)
使列num的值递增增加。
需要注意的是在使用update语句里,可能会报错:Error Code 1175 You are using safe update mode。也就是如果没有加where限制条件更新值是不允许的。这里我们关闭安全更新模式:
SET SQL_SAFE_UPDATES = 0;
通过上述步骤,我们给原表增加了递增的连续编号列num列。我们现在就可以根据num列进行随机抽样。
set @max=7142;set @min=1;select * from AppleStore a join (select floor(@min+(@max-@min+1)*rand()) as num from AppleStore limit 100) b on a.num=b.numlimit 100;
解释:我们将num列的最大编号、最小编号分别命名为变量@max和@min。
select floor(@min+(@max-@min+1)*rand()) as numfrom AppleStorelimit 100
该子句的作用是随机生成100个num序号。其中floor()
函数是对一个数向下取整,如floor(1.2)=1,这里采用向下取整,而不使用四舍五入的原因是防止抽样出的数据超过序号的最大值。该子句查询结果,我们重命名为表b,将表a,表b通过序号内连接,查找出b表中随机抽样出的100个序号所对应的数据。可以看出我们对序号的要求并不需要从1开始,它可以从任意值开始,只要序号是连续的。本方法在数据量大的情况下也有较快的查询速度。
上面我们添加num列是直接在原表上添加列并生成递增连续编号,很多时候修改原数据表是不妥的,可以使用with as
将新增num列后的查询表结果作为可以被引用的片断。
select *,row_number() over (order by id) as numfrom AppleStore
row_number() over (order by id) as num
,row_number函数将原表数据按id排序后生成序号,重命名为num。该查询语句实际就是在原AppleStore表基础上增加了列num,只是序号只显示在查询结果中,而不是对原表进行修改。我们利用with as
将AppleStore用增加的num列来替换。
set @max=7142;set @min=1;with AppleStore as (select *,row_number() over (order by id) as num from AppleStore)select * from AppleStore a join (select floor(@min+(@max-@min+1)*rand()) as num from AppleStore limit 100) b on a.num=b.numlimit 100;
青藤数据-审计师自己的平台