如何计算具有递归关系的表中唯一对的数量?

问题描述 投票:6回答:7

鉴于下表(people_table):

PersonId  CoupleId  
-------------------
   1        2  
   2        1  
   3        (null)  
   4        5  
   5        4  

通过编写类似于此的查询

Select count(?) from people_table

我希望2作为计数结果

sql oracle
7个回答
1
投票

我认为最简单的方法是:

select count(*)
from people_table
where PersonId < CoupleId  ;

为什么这样做?好吧,一对夫妇中的两个人有不同的ID。其中一个必须比另一个小,这就算其中一个。

这也过滤掉了NULL值。

注意:这假设您的数据格式正确 - 也就是说,一对夫妇中的两个人都在表中作为单独的行。


4
投票
select count(*) from table
where personID in (select coupleID from table)
and coupleID in (select personid from table)
and coupleID > personID

希望能帮助到你!


2
投票

逻辑

  • 使用内连接+连接表的PersonId =你的表的CoupleId和连接表的CoupleId =你的表的PersonId
  • 因为内连接将获得双行,所以它必须得到count(1) / 2计数。

架构(Oracle v11g)

CREATE TABLE T
    ("PersonId" int, "CoupleId" int)
INSERT ALL 
    INTO T ("PersonId", "CoupleId")
         VALUES (1, 2)
    INTO T ("PersonId", "CoupleId")
         VALUES (2, 1)
    INTO T ("PersonId", "CoupleId")
         VALUES (3, null)
    INTO T ("PersonId", "CoupleId")
         VALUES (4, 5)
    INTO T ("PersonId", "CoupleId")
         VALUES (5, 4)
SELECT * FROM dual

不允许使用PersonId和CoupleId重复版本

select count(1) / 2 cnt  from T T1
inner join T  T2 on T1."PersonId" = T2."CoupleId" and T1."CoupleId" = T2."PersonId"

cnt
---
2

允许PersonId和CoupleId重复版本

with cte as (
    select distinct * from T
)
select count(1) / 2 cnt  from CTE T1
inner join CTE T2 on T1."PersonId" = T2."CoupleId" and T1."CoupleId" = T2."PersonId"

cnt
---
2

View on db<>fiddle


2
投票

你可以将least()greatest()函数应用于personidcoupleidgroup by他们,最后计算行数:

select count(*) counter from (
  select least(personId, coupleId), greatest(personId, coupleId)  
  from people_table
  where personId is not null and coupleId is not null
  group by least(personId, coupleId), greatest(personId, coupleId)
)

demo


1
投票

下面是使用连接的查询 -

 with table1 as ( 
select 1 as PersonId , 2 as CoupleId from dual
union 
select 2 as PersonId , 1  as CoupleId from dual
union
select 3 as PersonId , null as CoupleId from dual 
union 
select 4 as PersonId , 5 as CoupleId from dual
union
select 5 as PersonId , 4 as CoupleId from dual)
select count(*) from table1 t1 inner join table1 t2 on t1.personId=t2.coupleid and t1.coupleId=t2.personId
where t1.personId>t1.coupleId;

1
投票

您可以“规范化”列以先获得较低的值,然后应用distinct来删除重复项:

SELECT Count(*)
FROM 
 (
   SELECT DISTINCT Least(PersonID, CoupleID) AS a, Greatest(PersonID, CoupleID) AS b
   FROM nodupes
   WHERE PersonID IS NOT NULL 
     AND CoupleID IS NOT NULL
 ) dt

0
投票

首先,在PersonId和CoupleId列中计算具有相同值的对,然后删除所有小于2的行,然后计算结果集中的行。

with
  table1 as ( 
    select 1 as PersonId, 2 as CoupleId from dual union all
    select 2, 1 from dual union all select 3, null from dual union all
    select 4, 5 from dual union all select 5, 4 from dual union all
    select 4, 5 from dual union all select 2, 1 from dual
  )
select count(*) as qnt
from (
  select count(*) as qnt
  from table1
  group by case when PersonId < CoupleId then PersonId else CoupleId end,
           case when PersonId < CoupleId then CoupleId else PersonId end
  having count(*) > 1
);

输出:

       QNT
----------
         2

使用db<>fiddle在线测试。

© www.soinside.com 2019 - 2024. All rights reserved.