查找数据库中所有一对多的表,表中重复数据

最近在做项目中,遇到一个SQL优化,去除distinct关键字。

distinct关键字作为去重,会将结果集全部查出,然后对其排序,最后去除重复的数据。一般多出现于left join之后的表对于索引条件(on后的条件)是一对多的情况。

现在要去除distinct关键字,首先需要做的就是找到对于索引列,哪些表是一对多的情况。此篇就是关于如何在数据库中找到对于索引列是一对多的表,然后做后续的删除关键字操作。

1. 首先我们要查找到所有包含索引列的表

--查询所有含有JOB_ID 字段的表
--JOB_ID为索引列
select t.table_name
  from DBA_TAB_COLUMNS t
 where COLUMN_NAME = 'JOB_ID'

2. 查找到以后,就应该为其分类判断,首先如果job_id 作为主键,是不可能存在重复的,所以要剔除为主键的情况,其中ORACLE数据库的系统表,字段信息多为大写,要注意。这里我们查找到了表名和主键名

--查询所有含有JOB_ID 字段 且JOB_ID 字段不是主键的表 的 表名及其主键 
select a.TABLE_NAME,
       c.column_name
-- DBA_TAB_COLUMNS数据库中所有字段记录表 
       from DBA_TAB_COLUMNS a 
--user_constraints 数据库中主键信息表 
       left join user_constraints b 
       on a.TABLE_NAME = b.table_name
 --user_cons_columns 字段约束信息表
       left join user_cons_columns c 
       on c.constraint_name = b.constraint_name
       where a.COLUMN_NAME = 'JOB_ID'
--constraint_type = 'P'为主键约束
       and b.constraint_type = 'P' 
--主键不能为JOB_ID
       and c.column_name <> 'JOB_ID'

3.查询到的结果集,要对其进行循环判断。其中用到了数据库循环的方法,execute immediate的用法。

--对上面的结果集进行循环
--查找所有对于字段JOB_ID 包含多个的情况,即一个主键对应多个JOB_ID               
declare
     tab_name varchar2(100);
     col_name varchar2(100);
     v_sql varchar2(500);
     conNum number;
begin
     for item in (select a.TABLE_NAME,
               c.column_name 
               from DBA_TAB_COLUMNS a  -- DBA_TAB_COLUMNS数据库中所有字段记录表
               left join user_constraints b --user_constraints 数据库中主键信息表
               on a.TABLE_NAME = b.table_name
               left join user_cons_columns c  --字段约束表
               on c.constraint_name = b.constraint_name
               where a.COLUMN_NAME = 'JOB_ID'
               and b.constraint_type = 'P' --constraint_type = 'P'为主键约束
               and c.column_name <> 'JOB_ID') loop
                   tab_name := item.table_name; --结果集的表名
                   col_name := item.column_name; --结果集的主键名
                   --表名不能为变量,但可以将SQL语句定义成字符串,通过execute immediate来执行
                   --两个count分别计数主键字段个数,和去重后的外键个数,差不为0则表示对于外键,该表不是一对多的情况
                   execute immediate 'select count('||col_name||') - count(distinct job_id) from ' ||tab_name into conNum;
                   if conNum > 0 then
                      dbms_output.put_line(tab_name);
                   end if;
     end loop;
end;

4.最后的执行结果是:

此方法只是将一对多的表查到,并不能直接解决去除distinct问题(除非不包含这些表,但是用了distinct),找到表之后,还应对SQL继续分析,找到最适合的方法。

——————————————————————————————————

重复数据

SELECT *
  FROM JOB_AE_BL_PO PO
 WHERE (PO.PO_NO, PO.ARTICLE_NO, PO.REF_NO1, PO.REF_NO5, PO.REF_NO8) IN
       (SELECT PO_NO, ARTICLE_NO, REF_NO1, REF_NO5, REF_NO8
          FROM JOB_AE_BL_PO
         GROUP BY PO_NO, ARTICLE_NO, REF_NO1, REF_NO5, REF_NO8
        HAVING COUNT(*) > 1)

上述代码查出的是PO_NO, ARTICLE_NO, REF_NO1, REF_NO5, REF_NO8这些字段的重复(全部相同才算一条重复数据)

猜你喜欢

转载自blog.csdn.net/qq_42740899/article/details/100670342