Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.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
Sql 增量比较Oracle中两个表之间的多个值集或列表_Sql_Oracle11g - Fatal编程技术网

Sql 增量比较Oracle中两个表之间的多个值集或列表

Sql 增量比较Oracle中两个表之间的多个值集或列表,sql,oracle11g,Sql,Oracle11g,我试图比较两个Oracle表之间的两组值,如下所示。我试图查找表B中的数据组并将其与表A中的数据组进行匹配。表之间的组号是通用的 只有当表a中id下的所有组和值与表B中的组和值对相等时,才会将其视为匹配。我已用绿色突出显示了“匹配”。表A在ida值下可能有数量可变的组/值对。有些ID可能只有一个组/值对,有些ID可能有3个组/值对 比较示例 尝试(和错误!) 我想我必须使用某种计数,并尝试使用分区by对表a中的组进行计数。但是,我不知道如何在查询中使用它来进行顺序/多值比较。我查找了分层函数,但

我试图比较两个Oracle表之间的两组值,如下所示。我试图查找表B中的数据组并将其与表A中的数据组进行匹配。表之间的组号是通用的

只有当表a中id下的所有组和值与表B中的组和值对相等时,才会将其视为匹配。我已用绿色突出显示了“匹配”。表A在ida值下可能有数量可变的组/值对。有些ID可能只有一个组/值对,有些ID可能有3个组/值对

比较示例 尝试(和错误!) 我想我必须使用某种计数,并尝试使用分区by对表a中的组进行计数。但是,我不知道如何在查询中使用它来进行顺序/多值比较。我查找了分层函数,但意识到它们可能不适合这里。。处理此类数据比较的最佳方法是什么?谢谢你的帮助

万圣节快乐!:)

资料
它不是完美的,但match_strength 2表示两者都匹配,match_strength 1表示只匹配一列

select * from (
select a.*, b.*, case when (a.vala = b.valb and a.groupa = b.groupb) then 2 
                      when (a.vala = b.valb or a.groupa = b.groupb) then 1 
                      else 0 end as match_strength,
                  row_number() over (partition by a.rowid order by 
                  case when (a.vala = b.valb and a.groupa = b.groupb) then 2 
                      when (a.vala = b.valb or a.groupa = b.groupb) then 1 
                      else 0 end desc) r
from tab_a a, tab_b b)
where r = 1;

如果你想知道哪一列匹配,你可以使用ORDERBY子句。

我认为这不是所有的方法,但可能会让你开始。你可以做:

select a.*, b.*,
  count(case when a.groupa = b.groupb and a.vala = b.valb then a.ida end)
    over (partition by a.ida) match_count,
  count(distinct a.groupa||':'||a.vala)
    over (partition by a.ida) val_count
from tab_a a
full outer join tab_b b on b.groupb = a.groupa and b.valb = a.vala
where a.groupa <= 3;
然后将其用作CTE或内联视图并解码结果:

with t as (
  select a.ida, a.groupa, a.vala, b.groupb, b.valb,
    count(case when a.groupa = b.groupb and a.vala = b.valb then a.ida end)
      over (partition by a.ida) match_count,
    count(distinct a.groupa||':'||a.vala)
      over (partition by a.ida) val_count
  from tab_a a
  full outer join tab_b b on b.groupb = a.groupa and b.valb = a.vala
  where a.groupa <= 3
)
select ida, groupa, vala, groupb, valb,
  case
    when match_count = 0 then 'No - Value doesn''t match'
    when match_count = val_count and val_count = 1
      then 'Yes - Group and Value match'
    when match_count = val_count and val_count = 2
      then 'Yes - Both Group (1&2) and Values match'
    when match_count < val_count and val_count = 2 and valb is not null
      then 'No - Only group 1 matches'
    when match_count < val_count and val_count = 2 and valb is null
      then 'No - Only group 1 matches. Group 2 doesn''t'
    else 'Unknown scenario?'
  end as "Match?"
from t;
我认为这会得到您在示例中显示的匹配结果;不确定你没有展示的其他东西是否是你想要的。。。ID 97与三个组/值匹配,很容易做到:

    when match_count = val_count and val_count = 3
      then 'Yes - All Group (1&2&3) and Values match'

但如果这三场比赛中有一场或两场比赛的话,要想知道该展示什么就更难了。您还可以捕获确实匹配的最小和最大B值,并从缺少的值中计算出来;但是,您可能会添加第四个组,但它不会缩放。

此查询应该可以:

select a.ida
from tab_a a
where a.groupa||a.vala in 
  (select b.groupb|| b.valb from tab_b b where b.groupb = a.groupa )
group by a.ida
having count(distinct a.groupa||a.vala) = 
  (select count(distinct a1.groupa||a1.vala) 
    from tab_a a1 
    where a1.ida = a.ida)
解释一下:


假设要求查找所有
ida
,所有对
groupa,vala
都可以在
表b
中找到(没有关于失败原因的进一步信息),您可以使用下面的查询。内部查询实际上显示了失败的原因(如果您选择
*
而不仅仅是
ida
)。在这个解决方案中,只有一件不寻常的事情——我听说使用in-condition(和类似的)来表示对,或者通常的元组,而不是标量值,但直到今天我才使用它。我刚刚测试了你的数据,效果非常好

这在以下一般意义上起作用:没有必要假设
groupa
对于每个
ida
都是唯一的,或者对于
表b
也是唯一的;也就是说,
(ida,groupa)
在第一个表中不必是唯一的,在第二个表中也不必是唯一的

select distinct ida from tab_a where ida not in
      (select ida from tab_a where (groupa, vala) not in (select groupb, valb from tab_b));

   IDA
------
    57
    95
    94
    97

精神崩溃。我喜欢这个问题。我看到的唯一合乎逻辑的问题是,您能否保证每个组和值组合都是唯一的?我看到必须使用CTE来完成这项工作,首先确定匹配的数据,然后选择关闭CTE或子查询以确保组的所有记录匹配;如果不确定哪些使用了或没有使用Listag之类的工具。这是我将要考虑的一个挑战性问题。为什么只列出一些ID;例如,为什么58没有行?也许这是一个简单的a左连接B在a.GroupA=B.GroupB和a.ValA=B.ValA上,然后是非空B值和非空a值的计数。匹配计数=所有REOCRD匹配非匹配非空计数表示一些匹配,我们可以使用Listag或wm_concat来识别它们。而空值表示完全不匹配。仍在思考…您的目标是输出一个与比较结果相同的结果集吗?如果是,则
groupb
选项卡b
中是否唯一?如果不是,您如何知道在比较
a
中特定行时显示
b
中的哪个不匹配行?或者,您的目标是只输出那些匹配的行(这稍微容易一点)?谢谢大家的回答@xQbert-不,跨组的值不是唯一的。使用上面相同的示例,两个组可以具有相同的值,组2也可以具有值1感谢您的回答。我发现Alex的方法到目前为止最直观地帮助解决了这个问题@Alex-带有文本的报告只是为了说明,预期的输出只是表中的匹配项B@Kacper-感谢分享该方法。我用AND语句替换了第一个例子中的OR,结果似乎将一些不匹配标记为matches@Sofia-你的第二个评论是关于错误的答案*8-)不太清楚第一个评论是什么意思。如果您想在B中显示非匹配项的值,可以使用
coalesce(groupb,groupa)
或只需重复
groupa
——但无论哪种方式,都有必要将值显示两次吗?
IDA GROUPA VALA  IDB GROUPB VALB MATCH_COUNT  VAL_COUNT
--- ------ ---- ---- ------ ---- ----------- ----------
 50      1    4                            0          1
 56      1    5                            0          1
 57      1    1  752      1    1           2          2
 57      2  101  752      2  101           2          2
 58      1    1  752      1    1           1          2
 58      2  104                            1          2
 60      2  102                            0          1
 94      1    1  752      1    1           1          1
 95      1    1  752      1    1           2          2
 95      2  101  752      2  101           2          2
 96      1    1  752      1    1           1          2
 96      2  102                            1          2
 97      1    1  752      1    1           3          3
 97      2  101  752      2  101           3          3
 97      3  201  752      3  201           3          3
with t as (
  select a.ida, a.groupa, a.vala, b.groupb, b.valb,
    count(case when a.groupa = b.groupb and a.vala = b.valb then a.ida end)
      over (partition by a.ida) match_count,
    count(distinct a.groupa||':'||a.vala)
      over (partition by a.ida) val_count
  from tab_a a
  full outer join tab_b b on b.groupb = a.groupa and b.valb = a.vala
  where a.groupa <= 3
)
select ida, groupa, vala, groupb, valb,
  case
    when match_count = 0 then 'No - Value doesn''t match'
    when match_count = val_count and val_count = 1
      then 'Yes - Group and Value match'
    when match_count = val_count and val_count = 2
      then 'Yes - Both Group (1&2) and Values match'
    when match_count < val_count and val_count = 2 and valb is not null
      then 'No - Only group 1 matches'
    when match_count < val_count and val_count = 2 and valb is null
      then 'No - Only group 1 matches. Group 2 doesn''t'
    else 'Unknown scenario?'
  end as "Match?"
from t;
IDA GROUPA VALA GROUPB VALB Match?                                    
--- ------ ---- ------ ---- ------------------------------------------
 50      1    4             No - Value doesn't match                  
 56      1    5             No - Value doesn't match                  
 57      1    1      1    1 Yes - Both Group (1&2) and Values match   
 57      2  101      2  101 Yes - Both Group (1&2) and Values match   
 58      1    1      1    1 No - Only group 1 matches                 
 58      2  104             No - Only group 1 matches. Group 2 doesn't
 60      2  102             No - Value doesn't match                  
 94      1    1      1    1 Yes - Group and Value match               
 95      1    1      1    1 Yes - Both Group (1&2) and Values match   
 95      2  101      2  101 Yes - Both Group (1&2) and Values match   
 96      1    1      1    1 No - Only group 1 matches                 
 96      2  102             No - Only group 1 matches. Group 2 doesn't
 97      1    1      1    1 Yes - All Group (1&2&3) and Values match  
 97      2  101      2  101 Yes - All Group (1&2&3) and Values match  
 97      3  201      3  201 Yes - All Group (1&2&3) and Values match  
    when match_count = val_count and val_count = 3
      then 'Yes - All Group (1&2&3) and Values match'
select a.ida
from tab_a a
where a.groupa||a.vala in 
  (select b.groupb|| b.valb from tab_b b where b.groupb = a.groupa )
group by a.ida
having count(distinct a.groupa||a.vala) = 
  (select count(distinct a1.groupa||a1.vala) 
    from tab_a a1 
    where a1.ida = a.ida)
1. where clause gets all the rows from tab_a 
     that exist in tab_b for a group+val combo. 
     - So let's say there are 2 (out of 2) rows in tab_a 
       that match with 2(out of 3) rows in tab_b.

2. left hand side of the having clause adds 
      a condition to the found rows such that 
      total number of rows of distinct group+val must equal to
      - So here we start comparing that count 2

3. right hand side of the having clause 
      that provides the total number of 
      distinct group+val (regardless of any match with tab_b).
      - here we enforce that left hand side must be equal
        to the total number of rows found. So if in #2 above, 
        only 1 row of table_a matched (out of its 2 rows), 
        then #3 will exclude that set.
select distinct ida from tab_a where ida not in
      (select ida from tab_a where (groupa, vala) not in (select groupb, valb from tab_b));

   IDA
------
    57
    95
    94
    97