如何获得每个类别中存在但其他类别中不存在的项目的计数?

时间:2019-09-14 10:49:31

标签: sql postgresql

我有一张桌子,其中有不同的visit_types去医院。它们是InpatientOutpatientEmergency

enter image description here

我想知道仅在每个visit_type下出现但在其他visit_types下没出现的主题数。在上面的示例中

  

住院人数-4

     

门诊人数-2

     

紧急计数-3

我尝试了以下内容,但不确定是否正确?

SELECT count(DISTINCT PERSON_ID) FROM Visit WHERE PERSON_ID NOT IN 
(select distinct person_id from Visit where visit_type = 'Inpatient') 
AND VISIT_type = 'Outpatient';

SELECT count(DISTINCT PERSON_ID) FROM Visit WHERE PERSON_ID NOT IN 
(select distinct person_id from Visit where visit_type = 'Inpatient') 
AND VISIT_type = 'Emergency';

执行此操作时,它包括EmergencyOutpatient之间的常见主题吗?

如何正确获取计数?

3 个答案:

答案 0 :(得分:1)

  

我想知道仅在每个类别下出现的主题数,而在其他类别下则没有。

您可以按患者进行汇总,并跟踪类别。然后再次聚合:

select visit_type, count(*)
from (select patientId, min(visit_type) as visit_type
      from t
      group by patientId
      having min(visit_type) = max(visit_type)
     ) p
group by visit_type;

另一种方法使用group by,但在聚合之前进行过滤:

select visit_type, count(*)
from t
where not exists (select 1
                  from t t2
                  where t2.patientid = t.patientid and
                        t2.visit_type <> t.visit_type
                 )
group by visit_type;

注意:在这种情况下,count(*)正在对行进行计数。如果您的数据重复,请使用count(distinct visit_type)

我不知道“我将住院类别视为基本类别”是什么意思,但问题本身很清楚。

编辑:

我不清楚您想要的不同类别之间的关系。您可能会发现使用起来最灵活:

select visit_type, count(*)
from (select patientId,
             bool_or(visit_type = 'Inpatient') as has_inpatient,
             bool_or(visit_type = 'Outpatient') as has_oupatient,
             bool_or(visit_type = 'Emergency') as has_emergency,
             count(distinct visit_type) as num_visit_types
      from t
      group by patientId
     ) p
where num_visit_types = 1
group by visit_type;

此版本与前面的两个查询相同。但是,您可以使用has_标志进行其他过滤-例如,where num_visit_types = 1 or (num_visit_types = 2 and has_inpatient)如果您想要具有一种类型或一种类型加上“住院患者”的人。

答案 1 :(得分:1)

您可以使用此查询!

SELECT 
    C.visit_type,
    COUNT(*) AS count_per_visit_type
FROM (
    SELECT
        person_id
    FROM (
        SELECT
            person_id,
            ARRAY_AGG(DISTINCT visit_type) AS visit_type_array
        FROM visit
        GROUP BY person_id
    ) A 
    WHERE LENGTH(visit_type_array) = 1
) B
JOIN visit C
ON B.person_id = C.person_id
GROUP BY C.visit_type

答案 2 :(得分:1)

有一个CTE,它为每个person_id返回所有类型:

with cte as (
  select person_id, 
    sum(case visit_type when 'Inpatient' then 1 else 0 end) Inpatient,
    sum(case visit_type when 'Outpatient' then 1 else 0 end) Outpatient,
    sum(case visit_type when 'Emergency' then 1 else 0 end) Emergency
  from Visit
  group by person_id
)
select 
  case 
    when Inpatient > 0 then 'Inpatient' 
    when Outpatient > 0 then 'Outpatient' 
    when Emergency > 0 then 'Emergency'
  end visit_type,
  count(*) counter
from cte
group by visit_type

请参见demo
结果:

visit_type | counter
:--------- | ------:
Outpatient |       2
Emergency  |       3
Inpatient  |       4