大家好,我有下一张桌子
Name | Gender | Count(Gender)
BBC | M | 31
BBC | F | 1
BBC | B | 3
BBC | N | 160
M: Male
F: Female
B: Both
N: Not Specified
我需要将其分为三类。 M,F,N。
如何制作一个Case语句,当寄存器为B时,男性和女性的计数增加为1。
我需要一张这样的桌子。
Name | Gender | Count(Gender)
BBC | M | 34
BBC | F | 4
BBC | N | 160
我希望我能很好地解释自己。
感谢大家。
答案 0 :(得分:1)
我会通过使用条件聚合然后取消隐藏来实现:
SELECT * FROM (
SELECT name, SUM(CASE WHEN gender IN ('M','B') THEN 1 ELSE 0 END) AS "M"
, SUM(CASE WHEN gender IN ('F','B') THEN 1 ELSE 0 END) AS "F"
, SUM(CASE WHEN gender = 'N' THEN 1 ELSE 0 END) AS "N"
FROM my_table
GROUP BY name
) UNPIVOT ( count_gender FOR gender IN ("M","F","N") );
B
值在条件聚合下的M
(男性)和F
(女性)列下计算 - 然后我们可以将我们的列转换为行。假设您至少使用Oracle 11g - 对于Oracle 10g及更低版本,您将不得不使用Tim Biegeleisen给出的查询。
编辑:如果您有一个计数表(即,如果您的帖子中的表是原始数据而不是聚合的结果),那么替换SUM()
以上的计数列代替" 1":
SUM(CASE WHEN gender IN ('M','B') THEN count_gender ELSE 0 END) AS "M"
希望这有帮助。
答案 1 :(得分:1)
这是一种方法。也许不是最简单的代码,但我相信它非常有效。它使用不完整的交叉连接来复制'B'行 - 这样基本数据只读取一次。
with
inputs ( name, gender, cnt ) as (
select 'BBC', 'M', 31 from dual union all
select 'BBC', 'F', 1 from dual union all
select 'BBC', 'B', 3 from dual union all
select 'BBC', 'N', 160 from dual union all
select 'ZYX', 'M', 55 from dual union all
select 'ZYX', 'F', 12 from dual union all
select 'ZYX', 'B', 43 from dual union all
select 'ZYX', 'N', 123 from dual
)
select i.name
, case i.gender when 'B' then case h.flag when 1 then 'F'
else 'M'
end
else i.gender
end as gender
, sum(cnt) as cnt
from inputs i cross join
( select 1 as flag from dual union all select 2 from dual ) h
where h.flag = 1 or i.gender = 'B'
group by i.name
, case i.gender when 'B' then case h.flag when 1 then 'F'
else 'M'
end
else i.gender
end
order by name, gender
;
输出(来自我在WITH子句中创建的扩展测试数据):
NAME GENDER CNT
---- ------ ---
BBC F 4
BBC M 34
BBC N 160
ZYX F 55
ZYX M 98
ZYX N 123
答案 2 :(得分:0)
我没有看到这样做的方法,而没有为两个统计数据生成数据,以涵盖男性和女性。我们可以将一个查询联合起来,这个查询聚合了男性,两者都是一个,而一个是女性和两者。工会的前半部分还包括未指定,因为它需要从某个地方进入。
SELECT
Name,
CASE WHEN Gender IN ('M', 'B') THEN 'M' ELSE Gender END AS Gender,
SUM(cnt) AS cnt
FROM yourTable
WHERE Gender IN ('M', 'B', 'N')
GROUP BY
Name,
CASE WHEN Gender IN ('M', 'B') THEN 'M' ELSE Gender END
UNION ALL
SELECT
Name,
CASE WHEN Gender IN ('F', 'B') THEN 'F' END AS Gender,
SUM(cnt) AS cnt
FROM yourTable
WHERE Gender IN ('F', 'B')
GROUP BY
Name,
CASE WHEN Gender IN ('F', 'B') THEN 'F' END
ORDER BY
Name, Gender
答案 3 :(得分:0)
我认为其他答案过于复杂。我从字面上理解您的原始陈述 - 您有一张按性别分列的表格。如果这个假设不成立,答案会略有改变。只需使用案例陈述在男性和女性中包括B,然后汇总:
WITH yourTable AS (
SELECT 'BBC' AS Name, 'M' AS Gender, 31 AS cnt from dual UNION ALL
SELECT 'BBC', 'F', 1 from dual UNION ALL
SELECT 'BBC', 'B', 3 from dual UNION ALL
SELECT 'BBC', 'N', 160 from dual
)
SELECT
SUM(male)
,SUM(female)
,SUM(not_known)
FROM
(SELECT
gender
,cnt
,CASE
WHEN gender IN ('M','B') THEN cnt
ELSE 0
END male
,CASE
WHEN gender IN ('F','B') THEN cnt
ELSE 0
END female
,CASE
WHEN gender = 'N' THEN cnt
ELSE 0
END not_known
FROM
yourTable
)
;
答案 4 :(得分:-2)
WITH yourTable AS (
SELECT 'BBC' AS Name, 'M' AS Gender, 31 AS cnt from dual UNION ALL
SELECT 'BBC', 'F', 1 from dual UNION ALL
SELECT 'BBC', 'B', 3 from dual UNION ALL
SELECT 'BBC', 'K', 3 from dual UNION ALL
SELECT 'BBC', 'N', 160 from dual )select t.*,sum(cnt) over (partition by gender) from yourTable t where gender in('F','M','N')