Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
比较同一表中的两组数据-oracle_Oracle_Dataset_Comparison_Union - Fatal编程技术网

比较同一表中的两组数据-oracle

比较同一表中的两组数据-oracle,oracle,dataset,comparison,union,Oracle,Dataset,Comparison,Union,假设我有一个包含以下数据的表 +-------------------------------+ | UniqueID Name Dataset | +-------------------------------+ | 1 ABC1 A:B;C:D;E:F | | 2 ABC2 A:B;C:D;R:S | | 3 ABC3 C:4;G:5;A:B | | 4 ABC4 A:B;C:D;E:F

假设我有一个包含以下数据的表

+-------------------------------+
|   UniqueID  Name    Dataset   |
+-------------------------------+
| 1         ABC1    A:B;C:D;E:F |
| 2         ABC2    A:B;C:D;R:S |
| 3         ABC3    C:4;G:5;A:B |
| 4         ABC4    A:B;C:D;E:F |
+-------------------------------+
其中数据集是数据的组合,例如A:B,由分隔

实际上,我想做的是将每组数据与另一条记录进行比较,并通过比较“数据集”得到这样的结果来构建一幅图,如下图所示。这只是第一次比较

+--------------------------------------------------------------------------+
| UniqueID  Name    UniqueID   Name    Matched on  OnlyinBase OnlyinTarget |
+--------------------------------------------------------------------------+
| 1         ABC1    2          ABC2    A:B;C:D       E:F           R:S     |
| etc                                                                      |
+--------------------------------------------------------------------------+
执行上述操作的最佳方法是什么?

我认为您的示例数据集不正确

对于ID=2d,不应该用分号而不是逗号与R分隔吗? 对于ID=35,不应该用分号而不是冒号与A分隔吗? 我修复了它是否应该被修复,并编写了以下PL/SQL代码;我不知道在纯SQL中是否可以做到这一点。看一看,看它是否有用

它有什么作用?使用嵌套循环,将所有数据集拆分为行,并使用集合运算符INTERSECT,减号决定结果属于哪个组(匹配/仅在基中/仅在目标中)

SQL> select * from test;

        ID NAME DATASET
---------- ---- --------------------
         1 ABC1 A:B;C:D;E:F
         2 ABC2 A:B;C:D;R:S
         3 ABC3 C:4;G:5;A:B
         4 ABC4 A:B;C:D;E:F

SQL> set serveroutput on
SQL>
SQL> DECLARE
  2     l_matched   VARCHAR2 (20);
  3     l_base      VARCHAR2 (20);
  4     l_target    VARCHAR2 (20);
  5  BEGIN
  6     FOR cur_1 IN (  SELECT id, name, dataset
  7                       FROM test
  8                   ORDER BY id)
  9     LOOP
 10        FOR cur_2 IN (  SELECT id, name, dataset
 11                          FROM test
 12                         WHERE id > cur_1.id
 13                      ORDER BY id)
 14        LOOP
 15           -- Matched
 16           SELECT LISTAGG (col, ';') WITHIN GROUP (ORDER BY col)
 17             INTO l_matched
 18             FROM (    SELECT REGEXP_SUBSTR (cur_1.dataset,
 19                                             '[^;]+',
 20                                             1,
 21                                             LEVEL)
 22                                 col
 23                         FROM DUAL
 24                   CONNECT BY LEVEL <= REGEXP_COUNT (cur_1.dataset, ';') + 1
 25                   INTERSECT
 26                       SELECT REGEXP_SUBSTR (cur_2.dataset,
 27                                             '[^;]+',
 28                                             1,
 29                                             LEVEL)
 30                                 col
 31                         FROM DUAL
 32                   CONNECT BY LEVEL <= REGEXP_COUNT (cur_2.dataset, ';') + 1);
 33
 34           -- Only in base
 35           SELECT LISTAGG (col, ';') WITHIN GROUP (ORDER BY col)
 36             INTO l_base
 37             FROM (    SELECT REGEXP_SUBSTR (cur_1.dataset,
 38                                             '[^;]+',
 39                                             1,
 40                                             LEVEL)
 41                                 col
 42                         FROM DUAL
 43                   CONNECT BY LEVEL <= REGEXP_COUNT (cur_1.dataset, ';') + 1
 44                   MINUS
 45                       SELECT REGEXP_SUBSTR (cur_2.dataset,
 46                                             '[^;]+',
 47                                             1,
 48                                             LEVEL)
 49                                 col
 50                         FROM DUAL
 51                   CONNECT BY LEVEL <= REGEXP_COUNT (cur_2.dataset, ';') + 1);
 52
 53           -- Only in target
 54           SELECT LISTAGG (col, ';') WITHIN GROUP (ORDER BY col)
 55             INTO l_target
 56             FROM (    SELECT REGEXP_SUBSTR (cur_2.dataset,
 57                                             '[^;]+',
 58                                             1,
 59                                             LEVEL)
 60                                 col
 61                         FROM DUAL
 62                   CONNECT BY LEVEL <= REGEXP_COUNT (cur_2.dataset, ';') + 1
 63                   MINUS
 64                       SELECT REGEXP_SUBSTR (cur_1.dataset,
 65                                             '[^;]+',
 66                                             1,
 67                                             LEVEL)
 68                                 col
 69                         FROM DUAL
 70                   CONNECT BY LEVEL <= REGEXP_COUNT (cur_1.dataset, ';') + 1);
 71
 72           DBMS_OUTPUT.put_line (
 73                 cur_1.id
 74              || ' '
 75              || cur_1.name
 76              || ' '
 77              || cur_2.id
 78              || ' '
 79              || cur_2.name
 80              || ' '
 81              || rpad(l_matched, 20, ' ')
 82              || ' '
 83              || rpad(l_base, 20, ' ')
 84              || ' '
 85              || rpad(l_target, 20, ' '));
 86        END LOOP;
 87     END LOOP;
 88  END;
 89  /
1 ABC1 2 ABC2 A:B;C:D              E:F                  R:S
1 ABC1 3 ABC3 A:B                  C:D;E:F              C:4;G:5
1 ABC1 4 ABC4 A:B;C:D;E:F
2 ABC2 3 ABC3 A:B                  C:D;R:S              C:4;G:5
2 ABC2 4 ABC4 A:B;C:D              R:S                  E:F
3 ABC3 4 ABC4 A:B                  C:4;G:5              C:D;E:F

PL/SQL procedure successfully completed.

SQL>

一个查询中的替代解决方案:

with 
  -- sample data
  t(Id, Name, Dataset) as (
    select 1, 'ABC1', 'A:B;C:D;E:F' from dual union all
    select 2, 'ABC2', 'A:B;C:D;R:S' from dual union all
    select 3, 'ABC3', 'C:4;G:5;A:B' from dual union all
    select 4, 'ABC4', 'A:B;C:D;E:F' from dual ),
  -- end of sample data
  q as (
    select distinct id, name,
           trim(regexp_substr(t.dataset, '[^;]+', 1, ls.column_value)) as ds
      from t, table(cast(multiset(select level from dual 
                                  connect by level <= length(regexp_replace(t.dataset, '[^;]+'))+1) 
                         as sys.odcinumberlist)) ls),
  p as (select q1.id id1, q1.name name1, q2.id id2, q2.name name2, q1.ds set1, q2.ds set2, 
               max(case when q1.ds = q2.ds then 1 else 0 end) 
                   over (partition by q1.id, q2.id, q1.ds) m1, 
               max(case when q1.ds = q2.ds then 1 else 0 end) 
                   over (partition by q1.id, q2.id, q2.ds) m2
          from q q1 join q q2 on q1.id <> q2.id),
  a1 as (select distinct id1, id2, set1 ds from p where m1 = 0),
  a2 as (select distinct id1, id2, set1 ds from p where m1 = 1),
  a3 as (select distinct id1, id2, set2 ds from p where m2 = 0)
select t1.id id1, t1.name name1, t2.id id2, t2.name name2, 
       (select listagg(ds, ' ; ') within group (order by ds) 
          from a1 where id1 = t1.id and id2 = t2.id) l1, 
       (select listagg(ds, ' ; ') within group (order by ds) 
          from a2 where id1 = t1.id and id2 = t2.id) l2, 
       (select listagg(ds, ' ; ') within group (order by ds) 
          from a3 where id1 = t1.id and id2 = t2.id) l3
  from t t1
  join t t2  on t1.id <> t2.id;
Subbquery q使用从SO到的拆分技术之一。然后,我加入了数据,并计算了匹配/不匹配的单词。只因为函数listag不尊重distinct子句,所以需要子查询a1-a3


此解决方案比较1和4以及4和1。通过将t1.id t2.id和q1.id q2.id中的数据分隔符替换为我修复的示例数据分隔符,您可以将其更改为仅显示一次结果-抱歉!我修复了示例数据分隔符,感谢您指出-现在请通读您的答案!这很有效。我想知道是否有一种更快的方法来实现正则表达式,因为它的伸缩性似乎不太好……好吧,对于这种方法集,我的意思是,你必须将字符串拆分成行。我想任何其他方法都可能更慢。如果可能的话,修改您的数据模型,使其规范化为当前的数据模型-您不应该在同一列中存储不同的信息。因此,我应该先创建一个过程来拆分数据…然后尝试上述操作…抱歉,我不是pl/sql专家,我也不是开发人员..嗯,对。。。如果您是一名开发人员,这会更容易:当我说数据模型不正确时,这意味着您应该创建更多的表,删除或重新创建当前的表。我想你不会那么做的。只有一次,是的-您可能会编写一些代码来拆分数据并将结果存储到其他表中,但是-如果要多次使用这样的代码,这也不是一个好的解决方案。不幸的是,你在为别人的错误买单。
   ID1 NAME1    ID2 NAME2 L1            L2                L3
------ ----- ------ ----- ------------  ----------------  -------------
     1 ABC1       2 ABC2  E:F           A:B ; C:D         R:S
     1 ABC1       3 ABC3  C:D ; E:F     A:B               C:4 ; G:5
     1 ABC1       4 ABC4                A:B ; C:D ; E:F
     2 ABC2       1 ABC1  R:S           A:B ; C:D         E:F
     2 ABC2       3 ABC3  C:D ; R:S     A:B               C:4 ; G:5
     2 ABC2       4 ABC4  R:S           A:B ; C:D         E:F
     3 ABC3       1 ABC1  C:4 ; G:5     A:B               C:D ; E:F
     3 ABC3       2 ABC2  C:4 ; G:5     A:B               C:D ; R:S
     3 ABC3       4 ABC4  C:4 ; G:5     A:B               C:D ; E:F
     4 ABC4       1 ABC1                A:B ; C:D ; E:F
     4 ABC4       2 ABC2  E:F           A:B ; C:D         R:S
     4 ABC4       3 ABC3  C:D ; E:F     A:B               C:4 ; G:5
12 rows selected