在连接后显示表中的记录并按特定列分组

时间:2014-11-09 07:43:20

标签: sql database oracle join group-by

我有两个包含一些数据的表:

表1: abc

||entity_id| entity_title|  cust_code| cust_acc_no     ||
----------------------------------------------------------
|| AB101Z  |   IND       |    101Z   |    1234         ||    
|| AB101Z  |   PAK       |    101Z   |    1357         ||    
|| CD101Y  |   IND       |    101Y   |    2468         ||
|| EF101X  |   IND       |    101X   |    3579         ||    
|| JK201N  |   LKO       |    201N   |    5678         ||

表2: def

||entity_title| in_count|  out_quant||
---------------------------------------------
|| IND        |   10    |       7   ||     
|| LKO        |    7    |       7   ||     
|| PAK        |    5    |       2   ||   

加入表: abcdef

||entity_id| entity_title|  cust_code ||      
--------------------------------------------------
|| AB101Z  |    INDPAK   |     101Z   || 
|| CD101Y  |    INDPAK   |     101Y   ||         
|| EF101X  |    INDPAK   |     101X   || 

我想加入表 abc def 表格,这些表格会在表格 abcdef 中生成。

虽然加入两个表和记录将按entity_title分组。加入条件是in_count!=out_count。例如,在LKO这种情况下,entity_title不会成为结果表的一部分。

我需要将匹配条件的entity_title记录替换为表示匹配记录的第三条记录,例如,INDPAK是所有记录的替代,无论这些记录是IND还是PAK两者或者这两者中的任何一个。

我尝试提出一个解决方案,但无法形成单个查询。提前感谢建议的任何解决方案。

2 个答案:

答案 0 :(得分:0)

here可能会对您有所帮助:

select * from 
(
  select t1.entity_id, case when t1.entity_title in('IND','PAK') then 'INDPAK' else t1.entity_title end as entity_title, t1.cust_code
  from   abc t1 join def t2
  on     t1.entity_title = t2.entity_title
  where  t2.in_count <> t2.out_count

) t
group by t.entity_id, t.entity_title, t.cust_code

答案 1 :(得分:0)

此解决方案避免了硬编码。它包括三个步骤:

  • 第一个子查询识别具有不同计数的ENTITY_TITLE的公共(ENTITY_ID,CUST_CODE)组合。

  • 第二个子查询标识拥有这些组合的ENTITY_TITLE,并为它们派生复合ENTITY_TITLE。 (它使用LISTAGG,这是一个11gR2的东西,但在早期版本的数据库中有字符串连接的解决方法)。

  • 外部查询生成所需的输出,用复合ENTITY_TITLE替换原始的ENTITY_TITLE。

这是整件事。我承认我不喜欢它依赖DISTINCT子句来获得所需的输出,但是加入规则会产生不必要的重复。

with prs as 
    ( select abc.entity_id
             , abc.cust_code
      from abc
           join def
           on abc.entity_title = def.entity_title
      where def.in_count != def.out_quant
      group by abc.entity_id, abc.cust_code having count(*) > 1 
     )
   , ent as 
    ( select distinct abc.entity_title
               , listagg(abc.entity_title) 
                     within group (order by abc.entity_title)
                     over (partition by prs.entity_id, prs.cust_code) as cmp_entity_title
      from abc
           join prs
    on abc.entity_id = prs.entity_id
    and abc.cust_code = prs.cust_code  
     )
select distinct abc.entity_id   
       , ent.cmp_entity_title
       , abc.cust_code
from ent
    join abc
    on abc.entity_title = ent.entity_title   
order by abc.entity_id  
         , abc.cust_code
/

请注意,在数据的初始条件下,输出强烈依赖。如果您查看我的inevitable SQL Fiddle,您会看到我在设置中添加了其他行。

第一个评论出ABC记录......

/* insert into abc values ('AB101Z','BAN','101Z',     5151         );  */ 

..创建一个匹配的三元组BANINDPAK,它替换所有出现的BAN,IND或PAK。这是你的规则的合理结果,也是我所期望的。

另一个评论出ABC记录......

/* insert into abc values ('JK101X','TIB','101K',     3434         );  */ 

...创建第二个匹配对PAKTIB,其存在为PAK实体的记录生成多个结果。这也是你的规则的合乎逻辑的结果,但也许是一个不太令人期待的结果。