只保留左边的一条记录 table

Keep only one record from left table

我需要在内部联接后获取记录,而没有来自左侧的重复数据 table。

Parent table :
Parent id  parent name
1          Douglas 

Child table :
Parent id  child name
1             George
1             Michael 

通过经典的 Oracle Inner 连接,我得到了这个:

Parent id  parent name  child name 
1          Douglas      George
1          Douglas      Michael 

但我需要这个结果:(我需要空值而不是 parents 个名称)

Parent id  parent name  child name 
1          Douglas      George
Null       Null         Michael 

当然还有parents和children。

您想在 child id

上进行右联接
select p.parentid,p.parentname,c.childname
from parent p
right join child c
on p.parentid=c.childid

一种方法是使用 a CURSOR EXPRESSION:

select parent_id
       , parent_name
       , cursor ( select child_id
                         , child_name
                  from child
                  where child.parent_id = parent.parent_id )
from parent

渲染效果取决于您使用的客户端 运行。有些人比其他人更好地处理输出。

或者您可以将其视为显示问题。例如,在 SQL*Plus 中,您可以使用 BREAK ON parent_id ON parent_name 来抑制重复值。 Find out more

select parent.parent_id
       , parent.parent_name
       , child.child_id
       , child.child_name
from parent 
     join child
         on child.parent_id = parent.parent_id
order by parent.parent_id, child.child_id;

要完成这项工作,您必须订购。


"It seems more complicated than I thought. Is there other way without Cursor?"

那是因为结果集应该是平坦的而不是锯齿状的。调整查询以实现显示功能通常会导致笨拙或冗长 SQL。

说到这里,这里有另一个解决方案:

with cte as (
   select parent.parent_id
          , parent.parent_name
          , child.child_id
          , child.child_name
          , row_number() over (partition by parent.parent_id 
                                             order by child.child_id ) as prn
          , row_number() over (order by  parent.parent_id , child.child_id ) as rn
    from parent 
         join child
             on child.parent_id = parent.parent_id
)
select case when prn = 1 then parent_id else null end as parent_id
       , case when prn = 1 then parent_name else null end as parent_name
       , child_id
       , child_name
from cte
order by rn

这会生成两个行号,一个用于跟踪父代,一个用于对整个行集进行排序。

使用row_number()lag()lead(),像这里:

select case when rn = 1 then parent_id end parent_id, 
       case when rn = 1 then parent_name end parent_name, 
       child_id, child_name 
  from (select p.parent_id, p.parent_name, c.child_id, c.child_name, 
               row_number() over (partition by p.parent_id order by c.child_id) rn
          from parents p join children c on p.parent_id = c.parent_id)

rextester demo

 PARENT_ID PARENT_NAME   CHILD_ID CHILD_NAME
---------- ----------- ---------- ----------
         1 Douglas              1 George
                                2 Michael