加入同一个表返回一些列重复

时间:2017-03-03 08:00:39

标签: sql oracle

我有一个令人困惑的逻辑。我有一个表person_details,它有一个唯一的主键id和外键persid。另一个外键是common_idcommon_id基于1和2.如果为1,则表示asset。如果为2,则表示liability

person_details表:

| id  |  details         |persid |  common_id |
|_____|__________________|_______|____________|  
  200   asset details     30         1
  201   asset details2    30         1
  203   liability detail  30         2

我希望将资产和责任详细信息分开并返回单个连接查询。当我尝试一个简单的查询时,它会返回重复的责任条目。

select   a.details assetdet, 
         b.details   liabdetails,
         a.common_id assetid,
         b.common_id liabId 
from person_details a 
join person_details b 
    on a.persid = b.persid  
where a.common_id = 1 and
      b.common_id = 2 and
      a.persid = 30

现在它返回:

|  assetdet     |   liabdetails   |   assetid  |   liabId | 
|_______________|_________________|____________|__________|
 asset details   liability detail      1           2
 asset details2  liability detail      1           2

我想返回

|  assetdet     |   liabdetails   |   assetid  |   liabId | 
|_______________|_________________|____________|__________|
 asset details   liability detail      1           2
 asset details2    null                1          null

2 个答案:

答案 0 :(得分:0)

您似乎只想加入一组资产的第一行,其中第一行来自一组负债。如果是这样,那么一个选项是使用CTE并为两个组的每个记录分配行号。然后在连接条件中使用此选项以确保只有资产/负债的第一条记录匹配。

WITH cte AS (
    SELECT id, details, persid, common_id,
           ROW_NUMBER() OVER (PARTITION BY common_id ORDER BY id) rn
    FROM person_details
)

SELECT a.details assetdet,
       b.details liabdetails,
       a.common_id assetid,
       b.common_id liabId
FROM cte a 
LEFT JOIN cte b
    ON a.persid = b.persid AND
       a.rn = 1 AND
       b.rn = 1 AND
       b.common_id = 2 AND
       a.persid = 30
WHERE a.common_id = 1;

<强>输出:

enter image description here

答案 1 :(得分:0)

在某种程度上,这似乎是一个建模问题:person_details感觉它应该是两个表。无论如何,此解决方案使用子查询工厂将表拆分为两个结果集并使用左外连接。这样可以防止重复责任记录。

with asst as (
    select id
           , details
           , persid
           , row_number() over (order by id) rn
    from person_details
    where common_id = 1
)
, liab as (
    select id
           , details
           , persid
           , row_number() over (order by id) rn
    from person_details
    where common_id = 2
)   
select asst.details as  asset_details
       , liab.details as liability_details
       , asst.common_id as asset_id
       , liab.common_id as liability_id
from asst 
left outer join liab
    on asst.persid = liab.persid
    and asst.rn = liab.rn
where asst.persid = 30
/

此解决方案解决了您发布的数据的问题。如果遗产记录多于资产记录,则无效。在这种情况下,您需要一个完整的外部联接。