使用一个或多个条件链接和计数记录

时间:2012-07-05 14:38:17

标签: sql oracle join count group-by

我试图将一些记录链接在一起以识别兄弟群体。我们这样做的方法是识别共享相同父母的客户。

SQL示例如下:

SELECT
A.ClientID,
B.ParentID

FROM A
LEFT JOIN B ON B.ClientID to A.ClientID
AND B.REL_END is NULL AND B.REL_CODE = 'PAR'

哪个会以下列格式返回数据:

     Client ID     Parent ID
     1             A
     1             B
     2             C
     2             D
     3             C
     3             E
     4             C
     4             D

我希望如何显示如下:

     Client ID    No. of Siblings
     1            0
     2            2
     3            2
     4            2         

希望表格显示孩子1有0个兄弟姐妹(没有父母有2,3,4),孩子2有2个兄弟姐妹(3和4),孩子3有2个兄弟姐妹(2和4),孩子4有2个兄弟姐妹(2,3)。看起来它应该足够简单来实现这一目标,但我真的在努力思考如何!我认为这有点令人困惑,因为一个孩子可能只与另一个孩子共用一个父母而被视为兄弟姐妹。

希望这很清楚,谢谢。

编辑:为了说清楚,这个关系由一个孩子与另一个孩子共享一个父ID来识别(ids是唯一的,但我为这个例子提供了通用的)。因此,当孩子2,3和4都有一个id为C的父母时,他们被认为是兄弟姐妹。

3 个答案:

答案 0 :(得分:2)

您可以尝试此查询,它会向我显示所需的输出。

with c_data as (
    select a.clientid, b.parentid, count(a.clientid) over (partition by parentid order by     parentid) as c_parents
    FROM A
      LEFT JOIN B ON (B.ClientID = A.ClientID)
        AND B.REL_END is NULL AND B.REL_CODE = 'PAR'
)
select clientid as "Client ID", max(c_parents) -1 as "No of Siblings"
from c_data
group by clientid;

示例:

SQL> with c_data as (
  2  select a.clientid, b.parentid, count(a.clientid) over (partition by parentid order by parentid) as c_parents
  3  FROM A
  4  LEFT JOIN B ON (B.ClientID = A.ClientID)
  5  AND B.REL_END is NULL AND B.REL_CODE = 'PAR'
  6  )
  7  select clientid as "Client ID", max(c_parents) -1 as "No of Siblings"
  8  from c_data
  9  group by clientid;

 Client ID No of Siblings
---------- --------------
         1              0
         2              2
         4              2
         3              2

Transcurrido: 00:00:00.03
SQL>

使用分析函数,我们将所有客户端ID分配为与当前tupple相关的parentid进行分区,以计算所有具有相同父级的客户端。

在投影之后,我们得到每个客户的共同父项的最大数量,以及客户本身的子项1。

希望这有帮助!

问候!

答案 1 :(得分:1)

这很复杂。如果你可以为每个孩子准确地假设两个父母,那么你可以做以下事情:

select c.*, count(*) over (partition by min_parent, max_parent) - 1 as NumSiblings
from (SELECT A.ClientID, min(B.ParentID) as min_parent, max(b.parentid) as max_parent
      FROM A LEFT JOIN
           B
           ON B.ClientID to A.ClientID AND B.REL_END is NULL AND B.REL_CODE = 'PAR'
      group by a.clientid
     ) c

这样做是为每个客户计算两个父母。然后,它使用windows函数来计算具有完全相同父项的客户端数。 “-1”是因为所有孩子都被计算在内,我们不想计算当前的孩子。

如果您有两个以上的父母,则查询会更复杂。

如果您只想共享一个父级(而不是两个),那么您可以使用自联接来处理:

with cp as (SELECT A.ClientID, B.ParentID
            FROM A LEFT JOIN
                 B
                 ON B.ClientID to A.ClientID AND B.REL_END is NULL AND B.REL_CODE = 'PAR'
           )
select cp.client_id, count(distinct cp1.client_id) as NumSiblings
from cp left outer join
     cp cp1
     on cp.parent_id = cp1.parent_id and cp.client_id <> cp1.client_id
group by cp.client_id

答案 2 :(得分:0)

好吧,我不明白表和关系是如何制作的,但你可以这样做:

SELECT ClientID, sum(NumberOfSibling) as NumberOfSibling
from(
    SELECT A.ClientID, (select count(ClientID) 
                        from A2
                        LEFT JOIN B2 ON B2.ClientID to A2.ClientID
                        AND B2.REL_END is NULL AND B2.REL_CODE = 'PAR'
                        where B2.ParentID = B.ParentID) as NumberOfSibling
    FROM A
    LEFT JOIN B ON B.ClientID to A.ClientID
    AND B.REL_END is NULL AND B.REL_CODE = 'PAR'
) GROUP BY ClientID

说明:我接受了您的请求并修改了第二个结果,以返回拥有相同父级的兄弟姐妹的总和(即the select count(*) ...,这也是我不确定条件的部分)。并将其放入另一个由ClientID分组以获得2个父母的总和。