根据上一行填充本行的空白栏位,SQL处理方式

简介:

我在4年多前,写了一篇Excel处理空白Cell的文章,http://www.cnblogs.com/studyzy/archive/2010/04/07/1706203.html,其实在数据库中也会遇到这种情况。对于普通的OLTP系统来说,应该不会出现,主要是在做OLAP,导入外部数据源时,可能导入系统的就是带有空白记录的数据。

为了方便说明,我举了一个简单的例子,假设一个学生成绩表,有字段“学生ID”和“成绩”,学生ID是主键,自增,成绩只有NULL和1,2,3,4,5这几个值。在录入学生成绩的时候,如果成绩为NULL,就表示该学生成绩和上一个学生的成绩相同。现在要查询某个学生ID的成绩,该怎么查呢?或者要将成绩字段改为不允许为空,怎么把所有NULL的行填上成绩呢?

首先我们先建立示例表:

复制代码
 1  create  table t1
 2 (
 3 ID  int  identity  primary  key,
 4 Score  int  null
 5 );
 6  insert t1
 7  values( 3),( 4),( null),( 3),( null),( null),( 5);
 8 
 9  select  *
10  from t1
复制代码


NewImage

 

 

 

 

 

 从结果我们可以看到如果要查询学生6的成绩,那么应该先去查学生5的成绩,由于学生5也是空,所以要继续查前一个学生4的成绩,得到分数3,所以学生6的成绩是3.这显然是一个递归问题,如果一直是空,会继续递归下去,直到找到一个成绩为止。要在SQL中使用递归,那么第一个应该想到的就是公用表表达式CTE。关于CTE的语法和说明可以看MSDN:https://msdn.microsoft.com/zh-cn/library/ms186243.aspx

那么我们这里递归的终点是什么呢?是不为空的成绩,递归的链接条件是上一个学生ID=当前学生ID-1.于是我们可以将此次的公用表表达式写为:

复制代码
 1  with t
 2  as
 3 (
 4  select  *  from t1  where Score  is  not  null
 5  union  all
 6  select t1.ID,t.Score
 7  from t
 8  inner  join t1
 9  on t.ID + 1 =t1.ID
10  where t1.Score  is  null
11 )
12  select  *
13  from t
14  order  by ID;
复制代码

得到的结果为:

NewImage

这里的情况比较特殊ID是连续的,那么如果ID不连续会怎么样呢?我们试着删除ID=5

delete from t1 where ID=5

这个时候如果还是运行上面的CTE就会查不到ID=6的记录,因为inner join的条件不成立了。那么简单的办法就是使用开窗函数给每一行数据增加一列连续自增的列,SQL Server中的函数是ROW_NUMBER().这样就变成了两个CTE嵌套使用,请看代码:
复制代码
 1  with t1new
 2  as
 3 (
 4  select  *,ROW_NUMBER()  over( order  by ID)  as RowNo
 5  from t1
 6 )
 7 , t
 8  as
 9 (
10  select Id,Score,RowNo  from t1new  where Score  is  not  null
11  union  all
12  select t1new.ID,t.Score,t1new.RowNo
13  from t
14  inner  join t1new
15  on t.RowNo + 1 =t1new.RowNo
16  where t1new.Score  is  null
17 )
18 
19  select  *
20  from t
21  order  by ID
复制代码
NewImage

公用表表达式真的很强大,另外在使用View出Report的时候,也可以用CTE,因为在View中不能用临时表,所以使用CTE代替临时表是个不错的解决方案。

目录
相关文章
|
SQL Oracle 关系型数据库
SQL实现日期自动填充
在不同数据库用SQL实现日期自动填充的方法
484 0
|
SQL 关系型数据库 数据库
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 14 章 性能提示_14.4. 填充一个数据库
14.4. 填充一个数据库 14.4.1. 禁用自动提交 14.4.2. 使用COPY 14.4.3. 移除索引 14.4.4. 移除外键约束 14.4.5. 增加maintenance_work_mem 14.4.6. 增加max_wal_size 14.4.7. 禁用 WAL 归档和流复制 14.4.8. 事后运行ANALYZE 14.4.9. 关于pg_dump的一些注记 第一次填充数据库时可能需要插入大量的数据。
1579 0
|
SQL 缓存 监控
sql 索引 填充因子(转)
和索引重建最相关的是填充因子。当创建一个新索引,或重建一个存在的索引时,你可以指定一个填充因子,它是在索引创建时索引里的数据页被填充的数量。填充因子设置为100意味着每个索引页100%填满,50%意味着每个索引页50%填满。
701 0
|
SQL XML 数据格式
如何填充SQL 2005中的XML字段
SQL 2005 新增了XML数据类型,那么当填充一个XML字段的时候传输一个什么样的类型呢?答案是使用SqlXml类型。具体代码可以参考MSDNSpecifying XML Values as Command Parameters
524 0
|
SQL XML 数据格式
如何填充SQL 2005中的XML字段
SQL 2005 新增了XML数据类型,那么当填充一个XML字段的时候传输一个什么样的类型呢?答案是使用SqlXml类型。具体代码可以参考MSDNSpecifying XML Values as Command Parameters
|
4天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
40 10
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
14天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
15 0
|
4天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
50 6