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
)

在我们的例子中,我们将对单元格col2col3col4以及维度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中使用先前的非空值填充稀疏数据相关推荐

  1. sql server 数组_如何在SQL Server中实现类似数组的功能

    sql server 数组 介绍 (Introduction) I was training some Oracle DBAs in T-SQL and they asked me how to cr ...

  2. sql server 性能_如何在SQL Server中收集性能和系统信息

    sql server 性能 介绍 (Introduction) In this article, we're going through many of the tools we can use fo ...

  3. 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 ...

  4. sql server只读_如何在SQL Server 2016中为可用性组配置只读路由

    sql server只读 The SQL Server Always On Availability Groups concept was introduced the first time in S ...

  5. mfc三视图和斜等测图实现_如何在UE4中实现NPR(非真实感)渲染效果?

    如何在UE4中实现NPR(非真实感)渲染效果?本文作者尝试在UE4中制作了秋叶原南出口的画面,并分享了全部的制作过程,希望对大家有所帮助. 在虚幻引擎中制作秋叶原南出口 我经常在artstation上 ...

  6. sql server 监视_如何在SQL Server中监视对象空间增长

    sql server 监视 介绍 (Introduction) There are many situations in a DBA's life that lead him or her to mo ...

  7. python 条形图填充疏密_如何在python中绘制密度图?

    我有一个.txt文件,其中包含2D地图中规则间隔点的x,y值,第三个坐标是该点的密度.4.882812500000000E-004 4.882812500000000E-004 0.9072267 1 ...

  8. matlab 填充 多边形,algorithm – 如何在MATLAB中从无序边数据创建填充多边形?

    如果多边形为 convex,则可以使用函数 CONVHULL从顶点计算凸包,并使用绘图函数 PATCH绘制多边形.例如: x = [0 1 0 1]; %# Unordered x coordinat ...

  9. pl/sql 测试函数_如何在SQL单元测试中使用伪函数?

    pl/sql 测试函数 In this article series, we are exploring SQL unit testing, in general, and also we are r ...

  10. @sql 单元测试_如何在SQL单元测试中使用假表?

    @sql 单元测试 In this article on SQL unit testing, we will talk about how to isolate SQL unit tests from ...

最新文章

  1. 《设计模式解析(第2版)》
  2. Java 8默认方法会破坏你的(用户的)代码
  3. 操作系统 课堂练习题03【20道 经典题目】
  4. redis 都有哪些数据类型?分别在哪些场景下使用比较合适?
  5. 【转载】Linux下有趣的命令
  6. Java开发十大常用网站
  7. C#.NET验证码智能识别学习笔记---03#.Net中@符号的意思
  8. uni-app中的样式
  9. Spring Boot 返回 XML 数据,一分钟搞定!
  10. centos oracle 修改监听服务名_Oracle-Oracle DB、监听和oem开机启动
  11. oracle索引用不了,oracle使用索引与不使用索引的性能详析
  12. 高可用Redis(四):列表,集合与有序集合
  13. 惠普m1216硒鼓清零步骤_显示耗材余量错误怎么解决呢,一招搞定
  14. python get rect 函数_Pygame:如何正确使用get_rect()
  15. python单例模式解析_深度解密Python单例模式
  16. 【科普】当手机遭遇短信验证码轰炸,这几点尤其要注意
  17. 程序员的黑砖窑,东南亚博彩骗局详解
  18. Python+scrapy+mysql实现爬取磁力链接
  19. 再续!一篇带你了解那些适合日常使用的开源工具和应用(设计篇)
  20. 为什么机会总是留给有准备的人?这是我听过最好的答案

热门文章

  1. 告诉你三个实用的换性别特效软件
  2. DM7数据库ODBC的配置详解
  3. Java-简单实现房屋出租系统
  4. 美国通胀放缓幅度超预期 美元或面临进一步承压?
  5. 等保测评--网络安全等级保护实施指南
  6. a59s刷机包卡刷 oppo_OPPO A59S刷机包
  7. java电商三级地址_Java电商项目面试--收货地址模块
  8. 很无聊但是又很重要的 计算机网络基础知识 ---“互联网协议“
  9. 三菱PLC与触摸屏的连接不通解决方法
  10. HTML学生个人网站作业设计:宠物网站设计——萌宠有家(5页) HTML+CSS 简单DIV布局宠物介绍网页模板代码 DW学生个人网站制作成品下载