数据完整性问题查询修复逻辑oracle sql

Posted

技术标签:

【中文标题】数据完整性问题查询修复逻辑oracle sql【英文标题】:Data Integrity issue query fix logic oracle sql 【发布时间】:2020-05-03 20:58:30 【问题描述】:

我有一个表,在这个表中我有数据没有正确加载数据完整性问题,因为这是一个维度表,我们需要正确维护有效_dt_from和有效_dt_to和版本,下面是表格和示例数据

create table TEST (
    LOC_SID NUMBER(38,0),
    CITY VARCHAR2(180 BYTE),
    POSTAL_CD VARCHAR2(15 BYTE),
    EFFECTIVE_DT_FROM DATE,
    EFFECTIVE_DT_TO DATE,
    VERSION NUMBER(38,0)
);

Insert into TEST values (25101,'Assam',1153,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('01.01.17 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25102,'Assam',1153,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('31.12.99 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25103,'Assam',1290,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('01.01.17 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25104,'Assam',1290,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('31.12.99 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25105,'Assam',1310,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('01.01.17 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25106,'Assam',1310,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('31.12.99 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25107,'Assam',1781,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('01.01.17 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25108,'Assam',1781,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('31.12.99 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25109,'Assam',1982,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('01.01.17 23:59:59','DD.MM.YY HH24:MI:SS'),1);
Insert into TEST values (25110,'Assam',1982,to_date('01.01.00 00:00:00','DD.MM.YY HH24:MI:SS'),to_date('31.12.99 23:59:59','DD.MM.YY HH24:MI:SS'),1);

数据完整性检查查询

SELECT count(*) AS RowAffected
FROM
  (SELECT LOC_SID,
          VERSION,
          EFFECTIVE_DT_FROM,
          EFFECTIVE_DT_TO,
          CITY,
          POSTAL_CD
   FROM
     (SELECT t.*,
             LEAD(EFFECTIVE_DT_FROM, 1) OVER(PARTITION BY CITY, POSTAL_CD
                                             ORDER BY EFFECTIVE_DT_FROM) AS next_date,
             LEAD(VERSION, 1) OVER(PARTITION BY CTY, POSTAL_CD
                                   ORDER BY EFFECTIVE_DT_FROM) AS next_version
      FROM TEST t)
   WHERE valid_to != next_date
     OR VERSION = next_version)

现有数据集

LOC_SID  CITY    POSTAL_CD       EFFECTIVE_DT_FROM   EFFECTIVE_DT_TO  VERSION
    25101   ASSAM   1153            01.01.1900          31.12.2199          1
    25102   ASSAM   1153            01.01.1900          31.12.2199          1
    25103   ASSAM   1290            01.01.1900          31.12.2199          1
    25104   ASSAM   1290            01.01.1900          31.12.2199          1
    25105   ASSAM   1310            01.01.1900          31.12.2199          1
    25106   ASSAM   1310            01.01.1900          31.12.2199          1
    25107   ASSAM   1781            01.01.1900          31.12.2199          1
    25108   ASSAM   1781            01.01.1900          31.12.2199          1
    25109   ASSAM   1982            01.01.1900          31.12.2199          1
    25110   ASSAM   1982            01.01.1900          31.12.2199          1

预期数据集

LOC_SID     CITY    POSTAL_CD   EFFECTIVE_DT_FROM   EFFECTIVE_DT_TO  VERSION
    25101    ASSAM   1153         01.01.1900          01.01.2017          1
    25102    ASSAM   1153         01.01.2017          31.12.2199          2
    25103    ASSAM   1290         01.01.1900          01.01.2017          1
    25104    ASSAM   1290         01.01.2017          31.12.2199          2
    25105    ASSAM   1310         01.01.1900          01.01.2017          1
    25106    ASSAM   1310         01.01.2017          31.12.2199          2
    25107    ASSAM   1781         01.01.1900          01.01.2017          1
    25108    ASSAM   1781         01.01.2017          31.12.2199          2
    25109    ASSAM   1982         01.01.1900          01.01.2017          1
    25110    ASSAM   1982         01.01.2017          31.12.2199          2

我尝试了下面的查询,但这只会更新唯一的版本,但不能解决问题

merge into test t
using (
    select
        t.*,
        row_number() over(order by loc_sid asc) rn,
        count(*) over() cnt
    from test t
    where city = 'Assam'
) t1
on (t1.loc_sid = t.loc_id)
when matched the update set
    t.version = t1.rn,
    t.effective_dt_from = 
        case 
            when rn = 1 then t.effective_dt_from
            else date '2017-01-01' + rn - 2
        end,
    t.effective_dt_to = 
        case 
            when rn = cnt then t.effective_dt_to
            else date '2017-01-01' + rn - 1
        end

【问题讨论】:

【参考方案1】:

日期的逻辑很好,但是您需要row_number() 而非postal_cd 分区来管理version

merge into test t
using (
    select
        loc_sid,
        row_number() over(order by loc_sid asc) rn,
        count(*) over() cnt,
        row_number() over(partition by postal_cd order by loc_sid) version
    from test t
    where city = 'Assam'
) t1
on (t1.loc_sid = t.loc_sid)
when matched then update set
    t.version = t1.version,
    t.effective_dt_from = 
        case 
            when rn = 1 then t.effective_dt_from
            else date '2017-01-01' + rn - 2
        end,
    t.effective_dt_to = 
        case 
            when rn = cnt then t.effective_dt_to
            else date '2017-01-01' + rn - 1
        end

Demo on DB Fiddle

LOC_SID |城市 | POSTAL_CD | EFFECTIVE_DT_FROM | EFFECTIVE_DT_TO |版本 ------: | :---- | :-------- | :---------------- | :---------------- | ------: 25101 |阿萨姆邦 |第1153章00 年 1 月 1 日 | 2017 年 1 月 1 日 | 1 25102 |阿萨姆邦 |第1153章2017 年 1 月 1 日 | 2017 年 1 月 2 日 | 2 25103 |阿萨姆邦 | 1290 | 2017 年 1 月 2 日 | 2017 年 1 月 3 日 | 1 25104 |阿萨姆邦 | 1290 | 2017 年 1 月 3 日 | 2017 年 1 月 4 日 | 2 25105 |阿萨姆邦 | 1310 | 2017 年 1 月 4 日 | 2017 年 1 月 5 日 | 1 25106 |阿萨姆邦 | 1310 | 2017 年 1 月 5 日 | 2017 年 1 月 6 日 | 2 25107 |阿萨姆邦 | 1781 | 2017 年 1 月 6 日 | 2017 年 1 月 7 日 | 1 25108 |阿萨姆邦 | 1781 | 2017 年 1 月 7 日 | 2017 年 1 月 8 日 | 2 25109 |阿萨姆邦 | 1982 | 2017 年 1 月 8 日 | 2017 年 1 月 9 日 | 1 25110 |阿萨姆邦 | 1982 | 2017 年 1 月 9 日 | 99 年 12 月 31 日 | 2

【讨论】:

非常好 - 我会做一个详细的测试并回复你,谢谢你的解释 嗨@GMB - 我有一些查询问题,因为上面的查询正在重置所有数据集的有效 date_from , Effective_date_to 和版本,新要求只是重置几行 - 我问了一个新问题很容易从您这边获得快速建议 - ***.com/questions/61621677/…

以上是关于数据完整性问题查询修复逻辑oracle sql的主要内容,如果未能解决你的问题,请参考以下文章

Oracle_查询语句

oracle 一对多数据分页查询筛选

Oracle:PL/SQL中用SQL语句添加数据 中文出现乱码问题?[有图]

13 oracle数据库坏块-逻辑坏块(模拟/修复)

关于优化在大量数据上执行的 Oracle SQL 查询的建议/技巧

Oracle事务