根据上一行填充本行的空白栏位,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 *
from t1
从结果我们可以看到如果要查询学生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
where t1.Score is null
)
select *
from t
order by ID;
得到的结果为:
这里的情况比较特殊ID是连续的,那么如果ID不连续会怎么样呢?我们试着删除ID=5
delete from t1 where ID=
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 (
select Id,Score,RowNo from t1new where Score is not null
union all
select t1new.ID,t.Score,t1new.RowNo
from t
inner join t1new
on t.RowNo+1=t1new.RowNo
where t1new.Score is null
)
select *
from t
order by ID
公用表表达式真的很强大,另外在使用View出Report的时候,也可以用CTE,因为在View中不能用临时表,所以使用CTE代替临时表是个不错的解决方案。
根据上一行填充本行的空白栏位,SQL处理方式的更多相关文章
- printf回到上一行开头以及回到本行开头的方法
回到上一行开头 #include <stdio.h> #include <unistd.h> int main(void) { ; ){ printf("%d\n&q ...
- sql 循环处理表数据中当前行和上一行中某值相+/-
曾经,sql中循环处理当前行数据和上一行数据浪费了我不少时间,学会后才发现如此容易,其实学问就是如此,难者不会,会者不难. 以下事例,使用游标循环表#temptable中数据,然后让当前行和上一行中的 ...
- 17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。 (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和。) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1
17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行.请采用循环控制语句来实现. (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和.) 1 1 1 1 ...
- SqlServer 游标逐行更新数据,根据上一行的数据来更新当前行
工作中用到的记录一下,游标的详细定义及说明请百度 --游标格式化数据 DECLARE cursor_jxsmb CURSOR FOR --定义一个游标 SELECT F0 FROM dbo.JXSMB ...
- easyui获取选中行上一行的数据
text: 'XX', iconCls: 'icon-ok', handler: function () { var rowI ...
- jqgrid 选中行触发编辑,切换下一行时验证和异步保存上一行数据
有时,我们需要批量修改或填写一些相似的数据.可以以jqgrid表来显示,可能的效果如下: 选中触发行编辑参考:jqgrid 单击行启用行编辑,切换行保存原编辑行 本文主要说说验证和异步保存上一条数据的 ...
- 在linux上一行代码不用写实现自动采集+hadoop分词
在linux上一行代码不用写实现自动采集+hadoop分词 将下面的shell脚本保存成到xxx.sh,然后执行即可 cd /opt/hadoop mkdir spider wget -O spide ...
- 「SAP技术」SAP HU上面的'Obj.to Which HU Belongs'栏位初探
SAP HU上面的'Obj.to Which HU Belongs'栏位初探 HU02,创建一个新的HU, 保存之, HU03显示这个HU 189141203942, 其'obj.to Which H ...
- MATLAB:一个K×M的矩阵,第一列是1,其它都是0,从最后一行开始,每循环一次,最后一行的1往右边移一位,移动到末尾后溢出,重新回到最左边,同时上一行的1往右边移一位
问题:一个K×M的矩阵,第一列是1,其它都是0,从最后一行开始,每循环一次,最后一行的1往右边移一位,移动到末尾后溢出,重新回到最左边,同时上一行的1往右边移一位.上一行溢出时,上上一行的1移动一位, ...
随机推荐
- linux命令笔记
3步实现ssh login不用密码: 1 ssh-keygen (Create public and private keys) 2 ssh-copy-id -i ~/.ssh/id_rsa.pub ...
- handlebars模板替换
<html> <head> <meta charset="UTF-8" /> <!-- <script type="tex ...
- linux系统下nodejs安装过程随记
首先下载适合的版本.这里我使用的是node v.10.36 先介绍编译安装的详细过程. 下载该版本: wget http://nodejs.org/dist/v0.10.36/node-v0.10.3 ...
- android 网络通讯
//get方式请求网络数据 String urlPath="http://192.168.98.112:8080/CloudMusicPlayer/fragment1_1_lv2/json/ ...
- selenium webdriver自动化对日期控件的处理
用JS去掉日期输入框的readOnly属性. 代码如下: ----------------------------------------------------------------------- ...
- java枚举与.net中的枚举区别
通过一段时间的项目实践,发现java中的枚举与.net中的枚举有很大的差别,初期造成了我对java中的枚举一些错误理解及部分有缺陷的应用,其实追其原因还是因为我会习惯性的认为java的枚举在作用以及定 ...
- Intro.js 网站演示
Intro.js 为您的网站和项目提供一步一步的.更好的介绍 使用简单 引入 js 和 css,然后在代码中加入步骤和介绍. 快速小巧 7 KB 的 JavaScript 和 3 KB CSS,就是全 ...
- 记STM32F030多通道ADC DMA读取乱序问题
问题描述通过 uint16_t ConvData[8]保存DMA搬运的ADC转换数值,但是这个数组数值的顺序总是和ADC不是顺序对应的.比如用7个通道的ADC,当设置ADC_InitStructure ...
- iOS 判断数组是否为空
有人说可以用([array count]==0 )来判断是否为空,都是坑,如果array为空的话,执行count就会直接报错,程序崩溃退出. 正确判断NSArray是否为空的方法:用 (!array) ...
- 转载:HBASE配置说明
HBase 默认配置 ,原文:http://eclecl1314-163-com.iteye.com/blog/1474286 该文档是用hbase默认配置文件生成的,文件源是 hbase-defa ...