【问题标题】:Oracle SQL, how to compare and find mismatches between two tablesOracle SQL,如何比较和查找两个表之间的不匹配
【发布时间】:2020-06-24 19:18:26
【问题描述】:

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

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,所有记录都相同。

表一说明:

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

表2说明:

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

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

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

同样,“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天。请帮助解决这个问题

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    您可以编写查询,使用解析函数将表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 的条件。

    【讨论】:

      【解决方案2】:

      这个查询:

      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
      

      demo

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-02
        • 2023-03-06
        • 2016-09-25
        • 2014-07-03
        • 2015-05-23
        相关资源
        最近更新 更多