sql - 在 Oracle 表中查找重复和缺失 (null) 值
问题描述
我正在查找表中的错误并希望报告重复值和缺失值。我不确定执行此操作的最佳方法,并且正在寻找有关更好方法的建议来完成此操作。这是在 Oracle 12c 中。
这似乎达到了预期的结果:
SELECT a.id,
a.mainfield,
a.location,
b.counter
FROM maintable a
INNER JOIN (
SELECT mainfield,
Count(*) counter
FROM maintable
GROUP BY mainfield
HAVING Count(mainfield) > 1 OR mainfield IS NULL
) b ON a.mainfield = b.mainfield OR
( a.mainfield IS NULL AND b.mainfield IS NULL )
ORDER BY a.mainfield;
这有效并为我提供了 ID、可能为空的 MAINFIELD、重复的 MAINFIELD 值或空的 MAINFIELD 值的位置和计数。
我可以使用更简单或更高效的方法吗?我不得不承认我的 SQL 技能相当生疏。
样本数据可能有帮助,也可能没有帮助,但 ID 是主键,是一个数字,不能为空。其他字段都是 NVARCHAR2 并且可以为空。这些都没有被索引。这是输出的样子。有些记录是完全错误的。有些是明显的错别字。有些似乎是测试数据。
ID MAINFIELD LOCATION COUNTER
------- --------- --------------------------------- -------
16626 206000650 9A OLIVER ST CENTRAL STATION 2
18805 206000650 3 SWIFT CT CENTRAL STATION 2
22409 940000170 2 MARKET ST NEWARK DE 2
22003 940000170 1 MARKET ST NEWARK NJ 2
29533 970000030 95 MILL RD ANDOVER 2
20256 970000030 12 RAILROAD AVE 2
29018 978900050 44 BROAD STREET 2
28432 978900050 WASHINGTON ST AND HAMILTON AVE 2
21831 980700050 BROADWAY NEWTOWN 2
24147 980700050 MAIN STREET LEVITTOWN 2
26418 3
26738 TEST DATA 3
26755 3
最后三行有一个空主字段,并且有三个这样的记录(其中两个的位置也为空)。
在对上面的数据添加一些见解之后,我意识到我可能会考虑使用 NVL 来消除部分条件,如下所示(假设我选择的值在主字段中不是有效值):
SELECT a.id,
a.mainfield,
a.location,
b.counter
FROM maintable a
INNER JOIN (
SELECT mainfield,
Count(*) counter
FROM maintable
GROUP BY mainfield
HAVING Count(mainfield) > 1 OR mainfield IS NULL
) b ON NVL(a.mainfield,'***NULL***') = NVL(b.mainfield.'***NULL***')
ORDER BY a.mainfield;
这执行得更快一些,并且似乎产生了预期的结果。我一直在尝试其他选择但没有成功,所以这可能是最好的选择。
我放弃的一种替代方案可能适用于稍微不同的场景(但对我来说表现最差)是这个:
SELECT id,
mainfield,
location,
COUNT (id) OVER (PARTITION BY mainfield) counter
FROM maintable a
WHERE mainfield IS NULL
OR EXISTS(SELECT 1 from maintable b
WHERE mainfield = a.mainfield AND ROWID <> a.ROWID)
ORDER BY a.mainfield;
我真的很喜欢这种组合方式,并希望它会有些效率。我们并不是说它会运行好几天,但我正在尝试在 Oracle 中重新学习在我使用 SQL/DS 编码时可能曾经是一项技能。
如果上述任何一项让任何人想到更好的选择,我都会全力以赴。(例如,有没有办法在 WHERE 子句中引用计数器 [the COUNT (id) over PARTITION BY mainfield]?)
再次感谢。
解决方案
这似乎是 Balazs Papp 在 dba.stackexchange.com 板上提供的可读性、可靠性和效率之间的一个很好的折衷: https ://dba.stackexchange.com/a/210998/154392
SELECT * FROM (
SELECT id,
mainfield,
location,
COUNT (id) OVER (PARTITION BY mainfield) counter
FROM maintable a
) where counter > 1 or mainfield IS NULL
ORDER BY mainfield;
这是对原始帖子的最后一个替代方案的简化。它似乎并不比我原来的替代方案效率低(据我所知),但对我来说它更具可读性。
推荐阅读
- c# - PDF剪切矩形及其包含并添加到新的PDF文件IText
- javascript - 单击时如何获取表格相应单元格的值
- python - 使用数组匹配多列
- angular - 来自猫鼬模式的角度接口
- node.js - 无法从亚马逊获取访问令牌
- tcp - 在 Tokio 中使用 TcpStream 读取分段的 TCP 数据包
- wordpress - 在多语言网站中切换页脚
- javascript - 在 JavaScript 中解析非标准 JSON
- javascript - 语义 UI - iPhone 上的透明简单下拉菜单
- parse-platform - 使用 Back4app-Cli 部署本地解析服务器