MongoDB 怎么实现交叉汇总

交叉表作为一种常用的分类汇总表格,它可以用来显示表中某个字段的汇总值,并将它们分组;通过某一变量分组后作为行,然后用其它变量或变量的组合作为列,形成数据表进行统计分析。
如有集合 events, 统计每个用户的各个事件的数量;
按不同的人汇总事件数到表最后一列,按各事件汇总到最后一行,相关的数据与汇总表如下:

UserID  

EventID

Count

Date

1

1

10

2020-01-02

1

1

15

2020-01-02

1

2

12

2020-01-02

1

3

18

2020-01-03

2

1

5

2020-01-02

3

2

10

2020-01-02

  按 UserID 分组,将 EventID、Count 合并,则可进一步演化为:
UserID  

Evt1

Evt2

Evt3

Events

1

25

12

18

55







Total

30.0

60.0

60.0

70.0

用 MongoDB 脚本实现思路,针对每一个文档将每个事件的数据对齐,并增加字段记录当前事件数,相当于整理数据;再按用户分组,对各事件数量累计;按列数据累计追加到集合最后一行,最后过滤列显示,实现比较复杂。
可以使用集算器, 按人分组后进行汇总,实现比较容易。

集算器安装包可去润乾网站下载,运行时需要一个授权,免费版本就够用。
我们将上述事例实现步骤:

1、在集算器中编写脚本 events.dfx

A B
1 =mongo_open("mongodb://127.0.0.1:27017/raqdb") / 连接 MongDB 数据库
2 =mongo_shell(A1,"events.find(,{_id:0})") / 获取集合 events 数据
3 =A2.pivot@s(UserID;EventID,sum(Count);   1:"Evt1",2:"Evt2",   3:"Evt3").derive(Evt1+Evt2+Evt3:Events) / 按 UserID 分组统计 EventID 事件并汇总
4 >A3.insert(0,   "Total", A3.sum(Evt1), A3.sum(Evt2), A3.sum(Evt3), A3.sum(Events)) / 按各事件汇总追加到序列
5 >A1.close() / 关闭连接
  2、 执行脚本返回结果:
A3 UserID   Evt1 Evt2 Evt3 Events
1 25 12 18 55
2 5 (null) (null) 5
3 (null) 10 (null) 10
Total 30 22 18 70

A3按 UserID 分组,先得到本组的各个 EventID 事件数量,再汇总。

集算器提供了 JDBC 接口,脚本 events.dfx 很容易集成到 Java 中:
public static void doWork() {

    Connection con = null;
    java.sql.Statement st;
   
    try{
        Class.forName("com.esproc.jdbc.InternalDriver");
        con = DriverManager.getConnection("jdbc:esproc:local://"); 
        // 调用脚本 events.dfx
        st=con.createStatement(); 
        ResultSet rst = st.executeQuery("call events");
        System.out.println(rst);
    } catch(Exception e){
        System.out.println(e);
    } finally{
        // 关闭连接
        if (con!= null) {
            try {
                con.close();
            } catch(Exception e) {
                System.out.println(e);
            }
        }  
    }
}

集算器与 JAVA 集成的进一步信息可参考:《Java 如何调用 SPL 脚本》。