繁体   English   中英

Oracle SQL,如何比较和查找两个表之间的不匹配

[英]Oracle SQL, how to compare and find mismatches between two tables

我有两个表,在下面的结构中

Table 1

Type  ID  NAME     FROMPOS  SIZE
.doc   1  A Number    4      9
.doc   1  C Number   14     10
.doc   1  Total      24     10
.doc   1  Date       36      8
.doc   1  Data      null    null 

表 2

ID  TYPE   NAME  SEQUENCE SIZE SKIP

1    doc  A Number 1       9    3
1    doc  C Number 2      10    1
1    doc  Total    3      10    0
1    doc  Date     4       8    2
1    doc  Data     5      80    0
1    doc  Type     6       1    0

表1和表2的解释,表1和2中的记录是“csv”文件的结构

在 table1 和 table2 中都将具有类型和 id,所有记录都相同。

表1说明:

在第一条记录中,“A Number”和“FROMPOS”(FROM POSITION)值为4,这意味着前三个字符将是空格,帐号将在后面,即从第4个position到第12个position作为“大小” “A Number”的值为 9,对于“C Number”,我们跳过 position 并从 14 到 23 开始,因为该字段的“大小”为 10,对于所有其他记录也是如此。 Table1 列中的“NULL”可以忽略

表2说明:

Table2没有“FROMPOS”列,但有序列,表示csv中记录的输入顺序,Table1是旧格式,table2是新格式。

因此,在这两个表中,记录实际上将表示相同的格式,但方式不同。两个表中的类型、ID 和 SIZE 将相同

所以在表2中,“A Number”的“SEQUENCE”为1,“SKIP”是要跳过的字符数,即这里的“3”,所以它将从第4位开始,应该与表1中的“FROMPOS”匹配

类似地,“C Number”的“SEQUENCE”为 2,“SKIP”为 1,因此它将在“A Number”之后跳过 1 位,即它将跳过第 13 位并从 14 开始,“SIZE”为 10,因此以 23 结束.

同样,“Total”将从 24 开始,因为没有“SKIP”,长度为 10,并在第 34 位结束。 同样,它适用于所有记录。

我的目标是写一个 SQL 以确保表 2 中的 SEQUENCE、SKIP、SIZE 与表 1 中的 FROMPOS 和 SIZE 匹配

在 CSV 文件中考虑这种格式,

123456789, 1234567890,1000000, 24/06/20

注意:我尝试加入表格并且成功,但我无法编写逻辑来确保表 2 中的 SEQUENCE、SKIP、SIZE 与表 1 中的 FROMPOS 和 SIZE 匹配。 如果他们匹配我需要“成功”,如果他们不匹配需要“失败”

我是SQL的新手,我开始做这个项目来学习,坚持了4天。请帮助解决这个问题

您可以编写查询以使用分析 function 将表 2 数据转换为与表 1 相同格式的数据,然后将其与表 1 进行检查,如下所示:

Select t1.*, t2.*,
       Case when t1.frompos = t2.frompos and t1.size = t2.size 
       then 'SUCCESS' 
       else 'FAIL' 
       end as result
  from table1 t1 join
(Select t.id, t.type, t.name, t.sequence, t.size, t.skip,
       sum(skip+size) over (partition by t.id, t.type order by t.sequence) 
        - size + 1 as frompos,
       t.size
From table2 t) t2
On t1.id = t2.id
And t1.type = t2.type
And t1.name = t2.name

注意:根据您的要求添加处理 null 的条件。

这个查询:

with a as (
    select id, name, frompos, size_, type, 
           row_number() over (partition by id order by frompos) sequence,
           frompos - lag(frompos, 1, 0) over (partition by id order by frompos)
                   - lag(size_, 1, 0) over (partition by id order by frompos)
                   - case when row_number() over (partition by id order by frompos) = 1 
                          then 1 else 0 
                     end as skip
      from table1 )
select id, sequence, a.name, b.name, a.type a_type, b.type b_type, a.frompos, 
       a.size_ as a_size, a.skip as a_skip,
       b.size_ as b_size, b.skip as b_skip
  from a full join table2 b using (id, sequence)

为您的数据提供此结果:

ID  SEQUENCE NAME      NAME    A_TYPE    B_TYPE  FROMPOS  A_SIZE    A_SKIP  B_SIZE  B_SKIP
1   1        A Number  A Number    .doc    doc     4       9        3          9       3
1   2        C Number  C Number    .doc    doc    14      10        1         10       1
1   3        Total     Total       .doc    doc    24      10        0         10       0
1   4        Date      Date        .doc    doc    36       8        2          8       2
1   5        Data      Data        .doc    doc                     80          0
1   6        Type                          doc                      1          0

演示

根据需要在比较空值case when 第一行略有不同,我必须减去 1。我将size更改为size_ , Oracle 不喜欢它作为列名。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM