我有一个数据问题需要清理。基本上我有两张表存储“包”信息,一张表用于文档,一张表用于审计信息。我在包表中有条目引用不再存在且已被替换的文档(名称相同但 ID 不同),我想编写一个查询来查找所有错误的文档以及应该替换它们的新文档。唯一连接这两者的是审计表中存储文档名称(不是 id)的字符串值。
我在这里设置了一个示例架构:http://sqlfiddle.com/#!4/997bda/1
- package_s 是我们应用程序中包的单个值
- package_r 是我们应用程序中包的重复值
- (这些在 id 列中用相同的值连接)
- audit_info 是一个包中的所有审计信息
- docs 是可以附加到一个包中的所有文档
此查询查找带有错误附件的包(每个包可能不止一个)
select distinct ps.pkgname, pr.doc_list
from package_s ps, package_r pr
where ps.id = pr.id
and not exists (
select 1 from docs
where pr.doc_list = id
)
order by 1,2 asc
;
我需要使用以下规则构建查询:
- 我至少需要返回包 ID、位置值和新文档 ID(我将构建一个更新语句,将这个新文档 ID 放在与 package_r 表中的包 ID/位置匹配的行中)<
- 从审计信息中获取文档名称的方法是: SUBSTR(描述,0,INSTR(描述,'[')-2)
- 如果文档被添加然后被删除,它应该被忽略 (string_1)
- string_2 不得为“支持”
- 新文档必须匹配 状态='主人' 最新 = 1 酒馆 = '0'
现在我有一个半工作脚本,可以按包工作,但问题影响了 2000 多个包。我发现与包中正确附加的文档不匹配的审核条目,然后在文档表中搜索这些名称。这个问题是因为包和文档表之间没有直接链接,如果一个包上有多个问题附件,每个"new"文档每个位置值返回一次,即
package id bad doc id position new doc id
p1 d1 -1 d1-new
p1 d1 -1 d4-new
p1 d4 -2 d1-new
p1 d4 -2 d4-new
哪个新id进入哪个位置值并不重要,但是像这样的重复结果问题使得很难批量生成更新脚本,需要一些手动过滤。
这是一个有点复杂且独特的数据问题,因此我们将不胜感激。
最佳答案
此查询根据提供的信息工作:
with ai as (
select a1.audited_id id, dc.id doc_id, dc.docname,
row_number() over (partition by a1.audited_id order by dc.id) rn
from audit_info a1
join docs dc
on dc.state = 'Master' and dc.latest = 1 and dc.pub = '0'
and dc.docname = substr(a1.description, 1, instr(a1.description, '[')-2)
where string_1 = 'Added' and string_2 <> 'Supporting'
and not exists (
select * from audit_info a2
where a2.audited_id = a1.audited_id and string_1 = 'Removed'
and a2.description = a1.description )
and not exists ( -- here matching docs are eliminated
select 1 from package_r pr
where pr.id = a1.audited_id and pr.doc_list = dc.id ) ),
p as (
select ps.id, ps.pkgname, pr.doc_list, pr.position,
row_number() over (partition by ps.id order by doc_list) rn
from package_s ps
join package_r pr on pr.id = ps.id
where not exists ( select * from docs where pr.doc_list = docs.id )
)
select p.id, p.pkgname, p.doc_list, p.position
, ai.docname, ai.doc_id
from p join ai on ai.id = p.id and p.rn = ai.rn
order by p.id, p.doc_list, ai.doc_id
输出:
ID PKGNAME DOC_LIST POSITION DOCNAME DOC_ID
-- ------- -------- -------- ------- ------
p1 000001 d3 -3 doc3 d3-new
p1 000001 d4 -4 doc4 d4-new
p2 000002 d5 -2 doc5 d5-new
p4 000004 d6 -1 doc6 d6-new
编辑:评论中报告的问题的答案
it is identifying packages that do not have bad values, and then the doc_list column is blank,
请注意,identyfing 包的查询(我的子查询 p
)基本上是您的查询,我只是在那里添加了计数器。
我猜某些进程/应用程序或某人手动清除了 package_r
中的列 doc_list
。
如果您不想要这样的条目,只需在子查询 p
中添加条件 and trim(doc_list) is not null
。
for the ones it gets right on the package part (they have a bad value) it is bringing back the wrong docname/doc_id to replace the bad value with, it is a different doc_id in the list.
我只理解了一部分。您能否将此类条目添加到您的示例中(在 Fiddle 中或只是编辑您的问题并为它们添加有问题的输入行和预期输出?)
“哪个新 id 进入哪个位置值并不重要”。
我以这种方式进行的分配——如果我们有两个名称为“ABC”、“DEF”的旧文档,并且更正后的文档名称为“XXA”、“DE12”
那么它们将被链接为“ABC”->“DE12”和“DEF”->“XXA”(字母顺序似乎比完全随机更合理)。
在两个 row_number() 函数中分配随机更改 order by ...
到 order by null
。
关于sql - 如何在 Oracle 中查找表中的错误引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29634645/