-1

我有如下数据:

custid  date    gender  cust_type
25309   29/10/2018  M   A
25310   09/11/2018  F   B
25311   10/11/2018  O   C
25312   18/09/2018  F   D
25313   18/09/2018  O   A
25314   18/09/2018  M   B
25315   18/09/2018  F   C
25316   18/09/2018  F   D
25317   19/09/2018  M   D
25318   19/09/2018  O   B

我的最终输出应如下所示:

季度总计 AMFO 总计 BMFO 总计 CMFO 总计 DMFO 2 1 1 3 1 1 1 2 0 1 1 3 1 2 0

在此处输入图像描述

我需要为每个 cust_type 计算不同客户的数量。在每个 cust_type 中,我需要 M、F、O(性别)的计数

应根据日期列计算每个季度的输出。我在网站上尝试了一些建议,但它给了我错误的计数,同时在案例语句中使用 sum。

目前我为每个季度运行单独的查询以获得 cust_type 计数和性别计数,如下所示:

SELECT INDIVIDUAL_TYPE,COUNT(DISTINCT CUST_ID) FROM TOT_POP_DET WHERE DATE < (TO_DATE('01-JAN-2020','DD-MON-YYYY')) GROUP BY CUST_TYPE

SELECT GENDER,COUNT(DISTINCT CUST_ID) FROM TOT_POP_DET WHERE DATE < (TO_DATE('01-JAN-2020','DD-MON-YYYY')) AND CUST_TYPE='OTHER' GROUP BY GENDER

在这里寻求帮助。

4

4 回答 4

1

您没有指定该QUARTER列的逻辑,所以我只是假设您的意思是日历年的季度(Jan-Mar = Q1,Apr-Jun = Q2 等)。如果您按季度和客户类型对信息进行分组,那么您可以旋转该信息以获取您想要的格式。

设置

create table cust_table as
select 25309 as custid ,  to_date('29/10/2018','dd/mm/yyyy') as date_val,  'M' as gender,  'A' as cust_type from dual union all
select 25310 as custid ,  to_date('09/11/2018','dd/mm/yyyy') as date_val,  'F' as gender,  'B' as cust_type from dual union all
select 25311 as custid ,  to_date('10/11/2018','dd/mm/yyyy') as date_val,  'O' as gender,  'C' as cust_type from dual union all
select 25312 as custid ,  to_date('18/09/2018','dd/mm/yyyy') as date_val,  'F' as gender,  'D' as cust_type from dual union all
select 25313 as custid ,  to_date('18/09/2018','dd/mm/yyyy') as date_val,  'O' as gender,  'A' as cust_type from dual union all
select 25314 as custid ,  to_date('18/09/2018','dd/mm/yyyy') as date_val,  'M' as gender,  'B' as cust_type from dual union all
select 25315 as custid ,  to_date('18/09/2018','dd/mm/yyyy') as date_val,  'F' as gender,  'C' as cust_type from dual union all
select 25316 as custid ,  to_date('18/09/2018','dd/mm/yyyy') as date_val,  'F' as gender,  'D' as cust_type from dual union all
select 25317 as custid ,  to_date('19/09/2018','dd/mm/yyyy') as date_val,  'M' as gender,  'D' as cust_type from dual union all
select 25318 as custid ,  to_date('19/09/2018','dd/mm/yyyy') as date_val,  'O' as gender,  'B' as cust_type from dual;

询问

SELECT year,
       quarter,
         NVL (a_m_total, 0)
       + NVL (a_f_total, 0)
       + NVL (a_o_total, 0)
       + NVL (b_m_total, 0)
       + NVL (b_f_total, 0)
       + NVL (b_o_total, 0)
       + NVL (c_m_total, 0)
       + NVL (c_f_total, 0)
       + NVL (c_o_total, 0)
       + NVL (d_m_total, 0)
       + NVL (d_f_total, 0)
       + NVL (d_o_total, 0)                                            AS quarter_total,
       NVL (a_m_total, 0) + NVL (a_f_total, 0) + NVL (a_o_total, 0)    AS a_total,
       NVL (a_m_total, 0)                                              AS a_m_total,
       NVL (a_f_total, 0)                                              AS a_f_total,
       NVL (a_o_total, 0)                                              AS a_o_total,
       NVL (b_m_total, 0) + NVL (b_f_total, 0) + NVL (b_o_total, 0)    AS b_total,
       NVL (b_m_total, 0)                                              AS b_m_total,
       NVL (b_f_total, 0)                                              AS b_f_total,
       NVL (b_o_total, 0)                                              AS b_o_total,
       NVL (c_m_total, 0) + NVL (c_f_total, 0) + NVL (c_o_total, 0)    AS c_total,
       NVL (c_m_total, 0)                                              AS c_m_total,
       NVL (c_f_total, 0)                                              AS c_f_total,
       NVL (c_o_total, 0)                                              AS c_o_total,
       NVL (d_m_total, 0) + NVL (d_f_total, 0) + NVL (d_o_total, 0)    AS d_total,
       NVL (d_m_total, 0)                                              AS d_m_total,
       NVL (d_f_total, 0)                                              AS d_f_total,
       NVL (d_o_total, 0)                                              AS d_o_total
  FROM (  SELECT EXTRACT (YEAR FROM date_val)                     AS year,
                 CEIL (EXTRACT (MONTH FROM date_val) / 3)         AS quarter,
                 cust_type,
                 SUM (CASE gender WHEN 'M' THEN 1 ELSE 0 END)     AS total_m,
                 SUM (CASE gender WHEN 'F' THEN 1 ELSE 0 END)     AS total_f,
                 SUM (CASE gender WHEN 'O' THEN 1 ELSE 0 END)     AS total_o
            FROM cust_table
        GROUP BY EXTRACT (YEAR FROM date_val), CEIL (EXTRACT (MONTH FROM date_val) / 3), cust_type)
       PIVOT (MAX (total_m) AS m_total, MAX (total_f) AS f_total, MAX (total_o) AS o_total
             FOR cust_type
             IN ('A' AS a, 'B' AS b, 'C' AS c, 'D' AS d));

结果

   YEAR    QUARTER    QUARTER_TOTAL    A_TOTAL    A_M_TOTAL    A_F_TOTAL    A_O_TOTAL    B_TOTAL    B_M_TOTAL    B_F_TOTAL    B_O_TOTAL    C_TOTAL    C_M_TOTAL    C_F_TOTAL    C_O_TOTAL    D_TOTAL    D_M_TOTAL    D_F_TOTAL    D_O_TOTAL
_______ __________ ________________ __________ ____________ ____________ ____________ __________ ____________ ____________ ____________ __________ ____________ ____________ ____________ __________ ____________ ____________ ____________
   2018          3                7          1            0            0            1          2            1            0            1          1            0            1            0          3            1            2            0
   2018          4                3          2            1            0            0          1            0            1            0          1            0            0            1          0            0            0            0
于 2020-09-25T14:33:33.030 回答
1

我使用“列表”作为源表,然后使用 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

尝试了一个解释希望它有帮助

于 2020-09-25T17:16:46.887 回答
1

按 DATEPART(QUARTER, [Date Column]) 进行分组,然后对需要计算的各个行执行 SUM(CASE ...)。

下面是使用您的示例数据的示例。

    Select 
         DATEPART(QUARTER, date) [Quarter],
         SUM(CASE WHEN cust_type = 'A' THEN 1 ELSE 0) [Total A],
         SUM(CASE WHEN cust_type = 'A' AND gender = 'M' THEN 1 ELSE 0) [A - Male],
         SUM(CASE WHEN cust_type = 'A' AND gender = 'F' THEN 1 ELSE 0) [A - Female],
         SUM(CASE WHEN cust_type = 'A' AND gender = 'O' THEN 1 ELSE 0) [A - Other],
         SUM(CASE WHEN cust_type = 'B' THEN 1 ELSE 0) [Total B],
         SUM(CASE WHEN cust_type = 'B' AND gender = 'M' THEN 1 ELSE 0) [B - Male],
         SUM(CASE WHEN cust_type = 'B' AND gender = 'F' THEN 1 ELSE 0) [B - Female],
         SUM(CASE WHEN cust_type = 'B' AND gender = 'O' THEN 1 ELSE 0) [B - Other],
         SUM(CASE WHEN cust_type = 'C' THEN 1 ELSE 0) [Total C],
         SUM(CASE WHEN cust_type = 'C' AND gender = 'M' THEN 1 ELSE 0) [C - Male],
         SUM(CASE WHEN cust_type = 'C' AND gender = 'F' THEN 1 ELSE 0) [C - Female],
         SUM(CASE WHEN cust_type = 'C' AND gender = 'O' THEN 1 ELSE 0) [C - Other],
         SUM(CASE WHEN cust_type = 'D' THEN 1 ELSE 0) [Total D],
         SUM(CASE WHEN cust_type = 'D' AND gender = 'M' THEN 1 ELSE 0) [D - Male],
         SUM(CASE WHEN cust_type = 'D' AND gender = 'F' THEN 1 ELSE 0) [D - Female],
         SUM(CASE WHEN cust_type = 'D' AND gender = 'O' THEN 1 ELSE 0) [D - Other] 
FROM 
         TOT_POP_DET  
WHERE 
         SNAPSHOT_DATE < (TO_DATE('01-JAN-2020','DD-MON-YYYY'))  
GROUP BY 
         DATEPART(QUARTER, date)

下面是甲骨文

Select 
         TO_NUMBER(TO_CHAR(date, 'QUARTER')) [Quarter],
         SUM(CASE WHEN cust_type = 'A' THEN 1 ELSE 0) [Total A],
         SUM(CASE WHEN cust_type = 'A' AND gender = 'M' THEN 1 ELSE 0) [A - Male],
         SUM(CASE WHEN cust_type = 'A' AND gender = 'F' THEN 1 ELSE 0) [A - Female],
         SUM(CASE WHEN cust_type = 'A' AND gender = 'O' THEN 1 ELSE 0) [A - Other],
         SUM(CASE WHEN cust_type = 'B' THEN 1 ELSE 0) [Total B],
         SUM(CASE WHEN cust_type = 'B' AND gender = 'M' THEN 1 ELSE 0) [B - Male],
         SUM(CASE WHEN cust_type = 'B' AND gender = 'F' THEN 1 ELSE 0) [B - Female],
         SUM(CASE WHEN cust_type = 'B' AND gender = 'O' THEN 1 ELSE 0) [B - Other],
         SUM(CASE WHEN cust_type = 'C' THEN 1 ELSE 0) [Total C],
         SUM(CASE WHEN cust_type = 'C' AND gender = 'M' THEN 1 ELSE 0) [C - Male],
         SUM(CASE WHEN cust_type = 'C' AND gender = 'F' THEN 1 ELSE 0) [C - Female],
         SUM(CASE WHEN cust_type = 'C' AND gender = 'O' THEN 1 ELSE 0) [C - Other],
         SUM(CASE WHEN cust_type = 'D' THEN 1 ELSE 0) [Total D],
         SUM(CASE WHEN cust_type = 'D' AND gender = 'M' THEN 1 ELSE 0) [D - Male],
         SUM(CASE WHEN cust_type = 'D' AND gender = 'F' THEN 1 ELSE 0) [D - Female],
         SUM(CASE WHEN cust_type = 'D' AND gender = 'O' THEN 1 ELSE 0) [D - Other] 
FROM 
         TOT_POP_DET  
WHERE 
         SNAPSHOT_DATE < (TO_DATE('01-JAN-2020','DD-MON-YYYY'))  
GROUP BY 
         TO_NUMBER(TO_CHAR(date, 'QUARTER'))
 
于 2020-09-25T17:39:40.467 回答
0

我希望答案可以帮助你。在这个fiddle中找到 SQL 的版本是 Oracle 11g。操作您的cte数据以生成并为您的年份和季度生成两列。之后,您需要COUNT根据您想要的参数执行一个。

with cte AS(SELECT custid, gender, cust_type, EXTRACT(YEAR FROM cust_date) AS cust_year,
CASE WHEN EXTRACT(MONTH FROM cust_date)<4 THEN 1
  WHEN EXTRACT(MONTH FROM cust_date)<7 THEN 2
  WHEN EXTRACT(MONTH FROM cust_date)<10 THEN 3
  ELSE 4
  END AS quarter
FROM your_Table)
SELECT gender, cust_type, cust_year, quarter, COUNT(custid)
FROM cte
GROUP BY gender, cust_type, cust_year, quarter
ORDER BY cust_year, quarter, cust_type
于 2020-09-25T14:29:07.133 回答