sql填充空值_如何在SQL中使用先前的非空值填充稀疏数据
sql填充空值
以下是所有与数据相关的技术中的一个非常普遍的问题,我们将针对这两个非常精简的基于SQL的解决方案进行研究:
如何用“先前的非空值”填充稀疏数据集的单元格?
问题
这个问题真的很简单, 在这个问题中我将重用Stack Overflow用户aljassi提供的示例 :
我们有一个包含“稀疏”数据的表:
Col1 Col2 Col3 Col4
----------------------
A 0 1 5
B 0 4 0
C 2 0 0
D 0 0 0
E 3 5 0
F 0 3 0
G 0 3 1
H 0 1 5
I 3 5 0
上面的数据集包含一些非零的有趣数据点,以及一些由零值建模的间隙。 在其他示例中,我们可以将零替换为NULL
,但这仍然是相同的问题。 所需的结果如下:
Col1 Col2 Col3 Col4
----------------------
A 0 1 5
B 0 4 5
C 2 4 5
D 2 4 5
E 3 5 5
F 3 3 5
G 3 3 1
H 3 1 5
I 3 5 5
请注意,所有生成的值都以红色突出显示,并且它们对应于最新的蓝色值。
如何使用SQL? 我们将研究两种解决方案:
使用窗口函数的解决方案
这是您应该寻找的解决方案,并且在链接的堆栈溢出问题中有两个答案都使用了窗口函数:
- 用户nop77svk使用
LAST_VALUE()
的解决方案 - 用户MT0使用
LAG()
的解决方案
两种解决方案大致相同。 它们的工作方式如下(使用Oracle语法):
WITH t(col1, col2, col3, col4) AS (SELECT 'A', 0, 1, 5 FROM DUAL UNION ALLSELECT 'B', 0, 4, 0 FROM DUAL UNION ALLSELECT 'C', 2, 0, 0 FROM DUAL UNION ALLSELECT 'D', 0, 0, 0 FROM DUAL UNION ALLSELECT 'E', 3, 5, 0 FROM DUAL UNION ALLSELECT 'F', 0, 3, 0 FROM DUAL UNION ALLSELECT 'G', 0, 3, 1 FROM DUAL UNION ALLSELECT 'H', 0, 1, 5 FROM DUAL UNION ALLSELECT 'I', 3, 5, 0 FROM DUAL
)
SELECTcol1,nvl(last_value(nullif(col2, 0)) IGNORE NULLS OVER (ORDER BY col1), 0) col2,nvl(last_value(nullif(col3, 0)) IGNORE NULLS OVER (ORDER BY col1), 0) col3,nvl(last_value(nullif(col4, 0)) IGNORE NULLS OVER (ORDER BY col1), 0) col4
FROM t
现在,让我们分解这些窗口函数:
NULLIF(colx,0)
只要我们在数据集中有一个可接受的“空”值,这就是产生NULL
值的一种简单方法。 因此,我们得到的不是NULL
而是零。 将此功能应用于我们的数据,我们得到:
Col1 Col2 Col3 Col4
----------------------
A NULL 1 5
B NULL 4 NULL
C 2 NULL NULL
D NULL NULL NULL
E 3 5 NULL
F NULL 3 NULL
G NULL 3 1
H NULL 1 5
I 3 5 NULL
之所以这样做,是因为现在我们可以利用一些排名函数可以使用的有用的IGNORE NULLS
子句,特别是LAST_VALUE()
或LAG()
。 我们现在可以写:
last_value(...) IGNORE NULLS OVER (ORDER BY col1)
在按col1
对行进行排序时,我们取当前行之前的最后一个非NULL
值:
- 如果当前行包含非
NULL
值,那么我们将使用该值。 - 如果当前行包含
NULL
值,那么我们将“向上”运行,直到达到非NULL
值 - 如果我们要“向上”并且没有达到任何非
NULL
值,那么我们得到NULL
这导致以下结果:
Col1 Col2 Col3 Col4
----------------------
A NULL 1 5
B NULL 4 5
C 2 4 5
D 2 4 5
E 3 5 5
F 3 3 5
G 3 3 1
H 3 1 5
I 3 5 5
请注意,对于大多数窗口函数,一旦指定了ORDER BY
子句,则将以下frame子句用作默认值:
last_value(...) IGNORE NULLS OVER (ORDER BY col1ROWS BETWEEN UNBOUNDED PRECEEDING AND CURRENT ROW
)
有很多关键字,但是一旦您掌握了很多窗口函数,它们的含义就不会那么晦涩难懂了。 我们建议阅读以下博客文章以了解有关它们的更多信息:
- ROW_NUMBER(),RANK()和DENSE_RANK()之间的区别
- 不要错过带有FIRST_VALUE(),LAST_VALUE(),LEAD()和LAG()的超凡SQL能力
最后,由于我们不希望这些NULL
值保留在结果中,因此我们只需使用NVL()
(或其他数据库中的COALESCE()
将其删除:
nvl(last_value(...) IGNORE NULLS OVER (...), 0)
很简单,不是吗? 请注意,在这种特殊情况下, LAG()
和LAST_VALUE()
将具有相同的效果。
使用MODEL子句的解决方案
每当您在(Oracle)SQL中遇到问题时,使用窗口函数开始变得难以解决时,Oracle MODEL
子句可能会为其提供“简便”的解决方案。 我在“ easy”上使用了引号,因为语法有点难以记住,但是其本质确实并不那么难。
MODEL
子句不过是一种Oracle专用的方言,用于在数据库中实现类似电子表格的逻辑。 我强烈建议阅读Oracle的相关白皮书,该白皮书很好地解释了该功能:
- http://www.oracle.com/technetwork/middleware/bi-foundation/10gr1-twp-bi-dw-sqlmodel-131067.pdf
这是您可以使用MODEL
解决问题的方法(并忍受):
WITH t(col1, col2, col3, col4) AS (SELECT 'A', 0, 1, 5 FROM DUAL UNION ALLSELECT 'B', 0, 4, 0 FROM DUAL UNION ALLSELECT 'C', 2, 0, 0 FROM DUAL UNION ALLSELECT 'D', 0, 0, 0 FROM DUAL UNION ALLSELECT 'E', 3, 5, 0 FROM DUAL UNION ALLSELECT 'F', 0, 3, 0 FROM DUAL UNION ALLSELECT 'G', 0, 3, 1 FROM DUAL UNION ALLSELECT 'H', 0, 1, 5 FROM DUAL UNION ALLSELECT 'I', 3, 5, 0 FROM DUAL
)
SELECT * FROM t
MODELDIMENSION BY (row_number() OVER (ORDER BY col1) rn)MEASURES (col1, col2, col3, col4)RULES (col2[any] = DECODE(col2[cv(rn)], 0, NVL(col2[cv(rn) - 1], 0), col2[cv(rn)]),col3[any] = DECODE(col3[cv(rn)], 0, NVL(col3[cv(rn) - 1], 0), col3[cv(rn)]),col4[any] = DECODE(col4[cv(rn)], 0, NVL(col4[cv(rn) - 1], 0), col4[cv(rn)]))
这里有三个有趣的子句:
DIMENSION BY子句
就像在Microsoft Excel电子表格中一样, DIMENSION
对应于每个电子表格单元格的连续,不同的索引,我们要通过该索引来访问该单元格。 在Excel中,总是有两个维(一个维用字母A..Z,AA..ZZ,…书写),另一个维用数字(1..infinity)书写。
使用MODEL
,您可以指定任意多个尺寸。 在我们的示例中,我们将只使用一个,即每行的行号,该行号由col1
排序(窗口函数的另一种用例)。
MEASURES子句
MEASURES
子句为每个“单元”指定单独的单元值。 在Microsoft Excel中,一个单元格只能有一个值。 在Oracle的MODEL
子句中,我们可以在一个“单元格”中一次处理多个值。
在这种情况下,我们将所有列都设为单元格。
RULES子句
这是MODEL
子句中真正有趣的部分。 在这里,我们指定要根据哪些规则来计算每个单个单元格的值。 语法很简单:
RULES (<rule 1>,<rule 2>,...,<rule N>
)
每个单独的规则都可以实现以下形式的分配:
RULES (cell[dimension(s)] = rule
)
在我们的例子中,我们将对单元格col2
, col3
和col4
以及维度rn
任何值(对于行号)重复相同的规则。 因此,作业的左侧是
RULES (col2[any] = rule,col3[any] = rule,col4[any] = rule,
)
右侧是一个平凡的(但看起来不平凡的)表达:
DECODE(col2[cv(rn)], 0, NVL(col2[cv(rn) - 1], 0), col2[cv(rn)])
让我们再次分解。
解码
DECODE
是一个简单实用的Oracle函数,它接受第一个参数,将其与参数2进行比较,如果它们相同,则返回参数3,否则返回参数4。它的作用类似于CASE
,有点冗长:
DECODE(A, B, C, D)-- The same as:CASE A WHEN B THEN C ELSE D END
简历(rn)
cv()
是特定于MODEL
“函数”,表示“当前值”。 在赋值的左侧,我们使用"any"
作为维度说明符,因此我们将此规则应用于rn
“ any”值。 为了访问特定的rn
值,我们只需编写cv(rn)
或“ rn的当前值”。
递归性
允许MODEL
子句的RULES
跨越一棵递归树(尽管不是图,所以不允许循环),其中每个单元格都可以基于前一个单元格进行定义,而前一个单元格又是基于其前身定义的。 我们通过col2[cv(rn) - 1]
,其中cv(rn) - 1
表示“当前行号减一”。
容易吧? 授予。 语法不是简单明了的,我们只是在摸索MODEL
可能的表面。
结论
SQL提供了一些很酷的方法来实现数据驱动的,声明性的数据规范。 MODEL
子句有点怪异,但同时功能非常强大。 窗口函数要容易得多,也要快一些。窗口函数应该是每个使用SQL的开发人员的工具链中的工具。
在本文中,我们展示了如何使用窗口函数或MODEL
填补稀疏数据中的空白。 一个类似的用例是运行总计。 如果本文引起了您的兴趣,建议您阅读有关SQL中计算运行总计的不同方法 。
翻译自: https://www.javacodegeeks.com/2015/12/fill-sparse-data-previous-non-empty-value-sql.html
sql填充空值
sql填充空值_如何在SQL中使用先前的非空值填充稀疏数据相关推荐
- sql server 数组_如何在SQL Server中实现类似数组的功能
sql server 数组 介绍 (Introduction) I was training some Oracle DBAs in T-SQL and they asked me how to cr ...
- sql server 性能_如何在SQL Server中收集性能和系统信息
sql server 性能 介绍 (Introduction) In this article, we're going through many of the tools we can use fo ...
- sql azure 语法_如何在SQL 2016中使用Azure Key Vault使用AlwaysOn配置TDE数据库
sql azure 语法 One of the recent tasks I undertook on configuring Transparent Data encryption (TDE) us ...
- sql server只读_如何在SQL Server 2016中为可用性组配置只读路由
sql server只读 The SQL Server Always On Availability Groups concept was introduced the first time in S ...
- mfc三视图和斜等测图实现_如何在UE4中实现NPR(非真实感)渲染效果?
如何在UE4中实现NPR(非真实感)渲染效果?本文作者尝试在UE4中制作了秋叶原南出口的画面,并分享了全部的制作过程,希望对大家有所帮助. 在虚幻引擎中制作秋叶原南出口 我经常在artstation上 ...
- sql server 监视_如何在SQL Server中监视对象空间增长
sql server 监视 介绍 (Introduction) There are many situations in a DBA's life that lead him or her to mo ...
- python 条形图填充疏密_如何在python中绘制密度图?
我有一个.txt文件,其中包含2D地图中规则间隔点的x,y值,第三个坐标是该点的密度.4.882812500000000E-004 4.882812500000000E-004 0.9072267 1 ...
- matlab 填充 多边形,algorithm – 如何在MATLAB中从无序边数据创建填充多边形?
如果多边形为 convex,则可以使用函数 CONVHULL从顶点计算凸包,并使用绘图函数 PATCH绘制多边形.例如: x = [0 1 0 1]; %# Unordered x coordinat ...
- pl/sql 测试函数_如何在SQL单元测试中使用伪函数?
pl/sql 测试函数 In this article series, we are exploring SQL unit testing, in general, and also we are r ...
- @sql 单元测试_如何在SQL单元测试中使用假表?
@sql 单元测试 In this article on SQL unit testing, we will talk about how to isolate SQL unit tests from ...
最新文章
- 《设计模式解析(第2版)》
- Java 8默认方法会破坏你的(用户的)代码
- 操作系统 课堂练习题03【20道 经典题目】
- redis 都有哪些数据类型?分别在哪些场景下使用比较合适?
- 【转载】Linux下有趣的命令
- Java开发十大常用网站
- C#.NET验证码智能识别学习笔记---03#.Net中@符号的意思
- uni-app中的样式
- Spring Boot 返回 XML 数据,一分钟搞定!
- centos oracle 修改监听服务名_Oracle-Oracle DB、监听和oem开机启动
- oracle索引用不了,oracle使用索引与不使用索引的性能详析
- 高可用Redis(四):列表,集合与有序集合
- 惠普m1216硒鼓清零步骤_显示耗材余量错误怎么解决呢,一招搞定
- python get rect 函数_Pygame:如何正确使用get_rect()
- python单例模式解析_深度解密Python单例模式
- 【科普】当手机遭遇短信验证码轰炸,这几点尤其要注意
- 程序员的黑砖窑,东南亚博彩骗局详解
- Python+scrapy+mysql实现爬取磁力链接
- 再续!一篇带你了解那些适合日常使用的开源工具和应用(设计篇)
- 为什么机会总是留给有准备的人?这是我听过最好的答案
热门文章
- 告诉你三个实用的换性别特效软件
- DM7数据库ODBC的配置详解
- Java-简单实现房屋出租系统
- 美国通胀放缓幅度超预期 美元或面临进一步承压?
- 等保测评--网络安全等级保护实施指南
- a59s刷机包卡刷 oppo_OPPO A59S刷机包
- java电商三级地址_Java电商项目面试--收货地址模块
- 很无聊但是又很重要的 计算机网络基础知识 ---“互联网协议“
- 三菱PLC与触摸屏的连接不通解决方法
- HTML学生个人网站作业设计:宠物网站设计——萌宠有家(5页) HTML+CSS 简单DIV布局宠物介绍网页模板代码 DW学生个人网站制作成品下载