我使用“列表”作为源表,然后使用 PIVOT 子句对性别类别明确地计数“custid”。并假设季度为“YYYY-Q”格式。作为最后一个查询,我将每个 cust_type 的每个性别的计数相加,以获得使用名为“cg”的数据透视表所需的结果。
with
list (custid, "date", gender, cust_type) as (
select 25309, to_date('29/10/2018', 'dd/mm/yyyy'), 'M', 'A' from dual union all
select 25310, to_date('09/11/2018', 'dd/mm/yyyy'), 'F', 'B' from dual union all
select 25311, to_date('10/11/2018', 'dd/mm/yyyy'), 'O', 'C' from dual union all
select 25312, to_date('18/09/2018', 'dd/mm/yyyy'), 'F', 'D' from dual union all
select 25313, to_date('18/09/2018', 'dd/mm/yyyy'), 'O', 'A' from dual union all
select 25314, to_date('18/09/2018', 'dd/mm/yyyy'), 'M', 'B' from dual union all
select 25315, to_date('18/09/2018', 'dd/mm/yyyy'), 'F', 'C' from dual union all
select 25316, to_date('18/09/2018', 'dd/mm/yyyy'), 'F', 'D' from dual union all
select 25317, to_date('19/09/2018', 'dd/mm/yyyy'), 'M', 'D' from dual union all
select 25318, to_date('19/09/2018', 'dd/mm/yyyy'), 'O', 'B' from dual
)
,cg as (
select * from (select custid, to_char("date", 'YYYY-Q') as quarter, cust_type, gender from list)
pivot (count(distinct custid) as gender for gender in('F' F, 'M' M, 'O' O))
)
select
quarter,
----------
sum(case when cust_type = 'A' then nvl(f_gender,0)+nvl(m_gender,0)+nvl(o_gender,0) else 0 end) as a_total,
sum(case when cust_type = 'A' then f_gender else 0 end) as a_f,
sum(case when cust_type = 'A' then m_gender else 0 end) as a_m,
sum(case when cust_type = 'A' then o_gender else 0 end) as a_o,
----------
sum(case when cust_type = 'B' then nvl(f_gender,0)+nvl(m_gender,0)+nvl(o_gender,0) else 0 end) as b_total,
sum(case when cust_type = 'B' then f_gender else 0 end) as b_f,
sum(case when cust_type = 'B' then m_gender else 0 end) as b_m,
sum(case when cust_type = 'B' then o_gender else 0 end) as b_o,
----------
sum(case when cust_type = 'C' then nvl(f_gender,0)+nvl(m_gender,0)+nvl(o_gender,0) else 0 end) as c_total,
sum(case when cust_type = 'C' then f_gender else 0 end) as c_f,
sum(case when cust_type = 'C' then m_gender else 0 end) as c_m,
sum(case when cust_type = 'C' then o_gender else 0 end) as c_o,
----------
sum(case when cust_type = 'D' then nvl(f_gender,0)+nvl(m_gender,0)+nvl(o_gender,0) else 0 end) as d_total,
sum(case when cust_type = 'D' then f_gender else 0 end) as d_f,
sum(case when cust_type = 'D' then m_gender else 0 end) as d_m,
sum(case when cust_type = 'D' then o_gender else 0 end) as d_o
from cg
group by quarter;
如果您的源表名称是 TOT_POP_DET 并且有列“custid”、“date”、“gender”、“cust_type”,那么您可以忽略我的数据准备“list”查询并以“cg”开头。我使用了 CTE(公用表表达式),但使用子查询也很好。“list”和“cg”是 CTE。我的意思是你可以开始
with cg as (
select * from (select custid, to_char("date", 'YYYY-Q') as quarter, cust_type, gender from TOT_POP_DET)
pivot (count(distinct custid) as gender for gender in('F' F, 'M' M, 'O' O))
)
,...
您会注意到“cg”是按季度和 cust_type 区分的计数。PIVOT 语法如下:
SELECT * FROM (SELECT column1, column2, .. FROM table(s) WHERE condition(s))
PIVOT (aggregate_function(column2) FOR column2 IN ( expr1, expr2, ... expr_n))
ORDER BY expression [ ASC | DESC ];
首先,从源表中选择需要的列,然后count(distinct custid)作为aggregation_function,gender FOR类别列,IN(gender list)。所以得到了按季度和 cust_type 设置的第一个结果。
QUARTER CUST_TYPE F_GENDER M_GENDER O_GENDER
2018-3 A 0 0 1
2018-3 B 0 1 1
2018-3 C 1 0 0
2018-3 D 2 1 0
2018-4 A 0 1 0
2018-4 B 1 0 0
2018-4 C 0 0 1
然后使用这个结果集,对每个案例的计数进行分组和求和,以转置数据以获得最终结果集。
QUARTER A_TOTAL A_F A_M A_O B_TOTAL B_F B_M B_O C_TOTAL C_F C_M C_O D_TOTAL D_F D_M D_O
2018-4 1 0 1 0 1 1 0 0 1 0 0 1 0 0 0 0
2018-3 1 0 0 1 2 0 1 1 1 1 0 0 3 2 1 0
此外,如果您在 PIVOT 中将“YYYY-Q”更改为“YYYY”并执行查询,则可以按年份获取结果,如下所示
QUARTER A_TOTAL A_F A_M A_O B_TOTAL B_F B_M B_O C_TOTAL C_F C_M C_O D_TOTAL D_F D_M D_O
2018 2 0 1 1 3 1 1 1 2 1 0 1 3 2 1 0
尝试了一个解释希望它有帮助