不同的条件计数以避免重叠
Distinct Conditional Counting to Avoid Overlap
考虑这个 table:
[Table1]
------------------------
| Person_ID | Yes | No |
|-----------|-----|----|
| 1 | 1 | 0 |
|-----------|-----|----|
| 1 | 1 | 0 |
|-----------|-----|----|
| 2 | 0 | 1 |
|-----------|-----|----|
| 2 | 0 | 1 |
|-----------|-----|----|
| 3 | 1 | 0 |
|-----------|-----|----|
| 3 | 1 | 0 |
|-----------|-----|----|
| 3 | 0 | 1 |
|-----------|-----|----|
| 3 | 1 | 0 |
------------------------
我需要对 Person_ID
进行不同的计数,以获得标记为 Yes
和 No
的人数。但是,如果某人有一个 No
实例,则无论他们有多少 Yes
,都应将其计为 No
,而不应计入 Yes
计数。
我的第一个想法是尝试类似的东西:
select count(distinct (case when Yes = 1 then Person_ID else null end)) Yes_People
, count(distinct (case when No = 1 then Person_ID else null end)) No_People
from Table1
但这将导致 3 被计入 Yes
和 No
计数。
我想要的输出是:
--------------------------
| Yes_People | No_People |
|------------|-----------|
| 1 | 2 |
--------------------------
我希望避免因必须针对每一行评估子查询而对性能造成影响,但如果必须这样做,我会接受。
您可以使用 window 函数对单个 person_id 的行进行排名,使 'No' 优先于 'Yes',但这需要子查询
select count(case when yes=1 then 1 end) as yes_count,
count(case when no=1 then no_count) as no_count
from (
select person_id, yes, no, row_number() over (order by no desc, yes desc) as rn
from table1
)
where rn = 1
内部子查询加上 where
过滤器将为每个 person_id 获取一行,优先考虑 'no' 条记录。
这当然假设 yes/no 是互斥的,如果是这样,您可能应该将模型更改为单个字段。
认为您需要使用 window 功能预先检查每个人
with t as (select 1 p_id, 1 yes, 0 no from dual
union all select 1 p_id, 1 yes, 0 no from dual
union all select 2 p_id, 0 yes, 1 no from dual
union all select 2 p_id, 0 yes, 1 no from dual
union all select 3 p_id, 1 yes, 0 no from dual
union all select 3 p_id, 0 yes, 1 no from dual
union all select 3 p_id, 1 yes, 0 no from dual)
, chk as (
select max(no) over (partition by p_id) n
, max(yes) over (partition by p_id) y
, p_id
from t)
-- select * from chk;
select count(distinct decode(y-n,1,p_id,null )) yes_people
, count(distinct decode(n,1,p_id,null )) no_people
from chk
group by 1;
先在个人层面汇总,然后再汇总:
select sum(yes_only) as yes_only,
sum(1 - yes_only) as no
from (select person_id,
(case when max(yes) = min(yes) and max(yes) = 1
then 1
end) as yes_only
from t
group by person_id
) t
您可以按如下方式使用条件聚合:
SQL> with table1 as (select 1 PERSON_ID, 1 yes, 0 no from dual
2 union all select 1 PERSON_ID, 1 yes, 0 no from dual
3 union all select 2 PERSON_ID, 0 yes, 1 no from dual
4 union all select 2 PERSON_ID, 0 yes, 1 no from dual
5 union all select 3 PERSON_ID, 1 yes, 0 no from dual
6 union all select 3 PERSON_ID, 0 yes, 1 no from dual
7 union all select 3 PERSON_ID, 1 yes, 0 no from dual)
8 SELECT
9 SUM(CASE WHEN NOS = 0 AND YES > 0 THEN 1 END) YES_PEOPLE,
10 SUM(CASE WHEN NOS > 0 THEN 1 END) NO_PEOPLE
11 FROM
12 (
13 SELECT
14 SUM(NO) NOS,
15 PERSON_ID,
16 SUM(YES) YES
17 FROM TABLE1
18 GROUP BY PERSON_ID
19 );
YES_PEOPLE NO_PEOPLE
---------- ----------
1 2
SQL>
干杯!!
你可以先按人物分组。
那么 CASE
的 Yes
人可以有一个不是 No
的条件。
SELECT
COUNT(CASE WHEN No = 0 AND Yes = 1 THEN Person_ID END) AS Yes_People,
COUNT(CASE WHEN No = 1 THEN Person_ID END) AS No_People
FROM
(
select Person_ID
, MAX(Yes) as Yes
, MAX(No) as No
FROM Table1
GROUP BY Person_ID
) q
考虑这个 table:
[Table1]
------------------------
| Person_ID | Yes | No |
|-----------|-----|----|
| 1 | 1 | 0 |
|-----------|-----|----|
| 1 | 1 | 0 |
|-----------|-----|----|
| 2 | 0 | 1 |
|-----------|-----|----|
| 2 | 0 | 1 |
|-----------|-----|----|
| 3 | 1 | 0 |
|-----------|-----|----|
| 3 | 1 | 0 |
|-----------|-----|----|
| 3 | 0 | 1 |
|-----------|-----|----|
| 3 | 1 | 0 |
------------------------
我需要对 Person_ID
进行不同的计数,以获得标记为 Yes
和 No
的人数。但是,如果某人有一个 No
实例,则无论他们有多少 Yes
,都应将其计为 No
,而不应计入 Yes
计数。
我的第一个想法是尝试类似的东西:
select count(distinct (case when Yes = 1 then Person_ID else null end)) Yes_People
, count(distinct (case when No = 1 then Person_ID else null end)) No_People
from Table1
但这将导致 3 被计入 Yes
和 No
计数。
我想要的输出是:
--------------------------
| Yes_People | No_People |
|------------|-----------|
| 1 | 2 |
--------------------------
我希望避免因必须针对每一行评估子查询而对性能造成影响,但如果必须这样做,我会接受。
您可以使用 window 函数对单个 person_id 的行进行排名,使 'No' 优先于 'Yes',但这需要子查询
select count(case when yes=1 then 1 end) as yes_count,
count(case when no=1 then no_count) as no_count
from (
select person_id, yes, no, row_number() over (order by no desc, yes desc) as rn
from table1
)
where rn = 1
内部子查询加上 where
过滤器将为每个 person_id 获取一行,优先考虑 'no' 条记录。
这当然假设 yes/no 是互斥的,如果是这样,您可能应该将模型更改为单个字段。
认为您需要使用 window 功能预先检查每个人
with t as (select 1 p_id, 1 yes, 0 no from dual
union all select 1 p_id, 1 yes, 0 no from dual
union all select 2 p_id, 0 yes, 1 no from dual
union all select 2 p_id, 0 yes, 1 no from dual
union all select 3 p_id, 1 yes, 0 no from dual
union all select 3 p_id, 0 yes, 1 no from dual
union all select 3 p_id, 1 yes, 0 no from dual)
, chk as (
select max(no) over (partition by p_id) n
, max(yes) over (partition by p_id) y
, p_id
from t)
-- select * from chk;
select count(distinct decode(y-n,1,p_id,null )) yes_people
, count(distinct decode(n,1,p_id,null )) no_people
from chk
group by 1;
先在个人层面汇总,然后再汇总:
select sum(yes_only) as yes_only,
sum(1 - yes_only) as no
from (select person_id,
(case when max(yes) = min(yes) and max(yes) = 1
then 1
end) as yes_only
from t
group by person_id
) t
您可以按如下方式使用条件聚合:
SQL> with table1 as (select 1 PERSON_ID, 1 yes, 0 no from dual 2 union all select 1 PERSON_ID, 1 yes, 0 no from dual 3 union all select 2 PERSON_ID, 0 yes, 1 no from dual 4 union all select 2 PERSON_ID, 0 yes, 1 no from dual 5 union all select 3 PERSON_ID, 1 yes, 0 no from dual 6 union all select 3 PERSON_ID, 0 yes, 1 no from dual 7 union all select 3 PERSON_ID, 1 yes, 0 no from dual) 8 SELECT 9 SUM(CASE WHEN NOS = 0 AND YES > 0 THEN 1 END) YES_PEOPLE, 10 SUM(CASE WHEN NOS > 0 THEN 1 END) NO_PEOPLE 11 FROM 12 ( 13 SELECT 14 SUM(NO) NOS, 15 PERSON_ID, 16 SUM(YES) YES 17 FROM TABLE1 18 GROUP BY PERSON_ID 19 ); YES_PEOPLE NO_PEOPLE ---------- ---------- 1 2 SQL>
干杯!!
你可以先按人物分组。
那么 CASE
的 Yes
人可以有一个不是 No
的条件。
SELECT
COUNT(CASE WHEN No = 0 AND Yes = 1 THEN Person_ID END) AS Yes_People,
COUNT(CASE WHEN No = 1 THEN Person_ID END) AS No_People
FROM
(
select Person_ID
, MAX(Yes) as Yes
, MAX(No) as No
FROM Table1
GROUP BY Person_ID
) q