Oracle SQL 11g:创建按用户ID和日期分组的标志的直方图

时间:2018-07-17 06:21:11

标签: sql oracle

我有一个看起来像这样的表:

+--------------------+---------------------+----+----+----+----+----+
| DATA_SUBSCRIBER_ID | MONTHLY_CALENDAR_ID | F1 | F2 | F3 | F4 | F5 |
+--------------------+---------------------+----+----+----+----+----+
|            3699060 | 01/07/2015          |  0 |  1 |  0 |  0 |  0 |
|            3699247 | 01/07/2015          |  0 |  0 |  1 |  1 |  0 |
|            3699342 | 01/08/2015          |  0 |  0 |  0 |  0 |  0 |
|            3699380 | 01/08/2015          |  1 |  0 |  0 |  0 |  1 |
|            3699506 | 01/09/2015          |  1 |  1 |  1 |  0 |  0 |
|            3699526 | 01/09/2015          |  0 |  1 |  1 |  1 |  1 |
+--------------------+---------------------+----+----+----+----+----+

我要进行查询,以使新表如下所示:

MONTHLY_CALENDAR_ID, SUM(F1+F2+F3+F4+F5), SUM(F1), SUM(F2), SUM(F3), SUM(F4), SUM(F5), USERS_WITH_0_FLAGS, USERS_WITH_1_FLAGS, USERS_WITH_2_FLAGS, USERS_WITH_3_FLAGS, USERS_WITH_4_FLAGS, USERS_WITH_5_FLAGS
+---+------------+---+---+---+---+---+---+---+---+---+---+---+---+
|   |     A      | B | C | D | E | F | G | H | I | J | K | L | M |
+---+------------+---+---+---+---+---+---+---+---+---+---+---+---+
| 1 | 01/07/2015 | 3 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
| 2 | 01/08/2015 | 5 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
| 3 | 01/09/2015 | 7 | 1 | 2 | 2 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
+---+------------+---+---+---+---+---+---+---+---+---+---+---+---+

基本上,我可以使用SUM完成所有列。但是我想统计每一行,并记录每个月有多少个标志。有什么想法如何查询吗?

我的尝试:

SELECT 
MONTHLY_CALENDAR_ID, 
SUM(F1 + F2 + F3 + F4 + F5 ), 
SUM(F1), SUM(F2), SUM(F3), SUM(F4), SUM(F5),
(SELECT COUNT(*) FROM a WHERE SUM(F1 + F2 + F3 + F4 + F5 )) AS USERS_WITH_0_FLAGS
FROM ANA_SUB a GROUP BY MONTHLY_CALENDAR_ID ORDER BY MONTHLY_CALENDAR_ID;

1 个答案:

答案 0 :(得分:0)

您可以通过以下方式执行此操作:首先计算每个用户的标志数,然后使用该数来填充列以指示该用户具有的标志数(例如,如果用户有0个标志,请用1个其他0、1个标志填充users_with_0_flags ,在users_with_1_flags中填充1个else 0,以此类推),然后在分组依据中使用它,例如:

WITH ana_sub AS (SELECT 3699060 data_subscriber_id, to_date('01/07/2015', 'dd/mm/yyyy') monthly_calendar_id, 0 f1, 1 f2, 0 f3, 0 f4, 0 f5 FROM dual UNION ALL
                 SELECT 3699247 data_subscriber_id, to_date('01/07/2015', 'dd/mm/yyyy') monthly_calendar_id, 0 f1, 0 f2, 1 f3, 1 f4, 0 f5 FROM dual UNION ALL
                 SELECT 3699342 data_subscriber_id, to_date('01/08/2015', 'dd/mm/yyyy') monthly_calendar_id, 0 f1, 0 f2, 0 f3, 0 f4, 0 f5 FROM dual UNION ALL
                 SELECT 3699380 data_subscriber_id, to_date('01/08/2015', 'dd/mm/yyyy') monthly_calendar_id, 1 f1, 0 f2, 0 f3, 0 f4, 1 f5 FROM dual UNION ALL
                 SELECT 3699506 data_subscriber_id, to_date('01/09/2015', 'dd/mm/yyyy') monthly_calendar_id, 1 f1, 1 f2, 1 f3, 0 f4, 0 f5 FROM dual UNION ALL
                 SELECT 3699526 data_subscriber_id, to_date('01/09/2015', 'dd/mm/yyyy') monthly_calendar_id, 0 f1, 1 f2, 1 f3, 1 f4, 1 f5 FROM dual),
    user_res AS (SELECT user_id,
                        monthly_calendar_id,
                        total_flags_per_user,
                        f1,
                        f2,
                        f3,
                        f4,
                        f5,
                        CASE WHEN total_flags_per_user = 0 THEN 1 ELSE 0 END users_with_0_flags,
                        CASE WHEN total_flags_per_user = 1 THEN 1 ELSE 0 END users_with_1_flags,
                        CASE WHEN total_flags_per_user = 2 THEN 1 ELSE 0 END users_with_2_flags,
                        CASE WHEN total_flags_per_user = 3 THEN 1 ELSE 0 END users_with_3_flags,
                        CASE WHEN total_flags_per_user = 4 THEN 1 ELSE 0 END users_with_4_flags,
                        CASE WHEN total_flags_per_user = 5 THEN 1 ELSE 0 END users_with_5_flags
                 FROM   (SELECT data_subscriber_id user_id,
                                monthly_calendar_id,
                                f1,
                                f2,
                                f3,
                                f4,
                                f5,
                                f1 + f2 + f3 + f4 + f5 total_flags_per_user
                         FROM   ana_sub))
SELECT row_number() OVER (ORDER BY monthly_calendar_id) rn,
       monthly_calendar_id a,
       sum(total_flags_per_user) b/*total_flags_per_month*/,
       SUM(f1) c/*f1_total*/,
       SUM(f2) d/*f2_total*/,
       SUM(f3) e/*f3_total*/,
       SUM(f4) f/*f4_total*/,
       SUM(f5) g/*f5_total*/,
       SUM(users_with_0_flags) h/*users_with_0_flags_total*/,
       SUM(users_with_1_flags) i/*users_with_1_flags_total*/,
       SUM(users_with_2_flags) j/*users_with_2_flags_total*/,
       SUM(users_with_3_flags) k/*users_with_3_flags_total*/,
       SUM(users_with_4_flags) l/*users_with_4_flags_total*/,
       SUM(users_with_5_flags) m/*users_with_5_flags_total*/
FROM   user_res
GROUP BY monthly_calendar_id;

给出:

RN A           B  C  D  E  F  G  H  I  J  K  L  M
-- ---------- -- -- -- -- -- -- -- -- -- -- -- --
 1 01/07/2015  3  0  1  1  1  0  0  1  1  0  0  0
 2 01/08/2015  2  1  0  0  0  1  1  0  1  0  0  0
 3 01/09/2015  7  1  2  2  1  1  0  0  0  1  1  0

我在这里假设(data_subscriber_id,monthly_calendar_id)上有一个唯一键或主键