最近又遇到了一个需求(每次都是用这个开头,感受本身都腻了-_-||),是根据已有的牌局记录表统计概括出天天每一个玩家在每一个游戏上面进行的局数。首先牌局记录表的结构大体以下:sql
其中log_date表示当局日期,game_id表示当局属于哪一个游戏,points是一个json类型的值,里面记录着参与这局游戏的玩家信息与得分状况,现有的原始数据以下:json
由于points是一个json数组,里面保存着用户的得分和user_id这些信息,所以能够考虑把points变为多行来实现分离每一个user_id的效果,如图所示:数组
把每一个user_id都分离以后就能够利用窗口函数统计每一个user_id对应的局数了,SQL语句以下:函数
SELECT game_id, user_id, SUM (COUNT(*)) OVER (PARTITION BY game_id, user_id) AS round_count FROM ( SELECT log_date, game_id, ( json_array_elements (points :: json) ->> 'user_id' ) AS user_id FROM game_record ) AS A GROUP BY game_id, user_id;
其中,over字句使得sum(count(*))函数被看成一个窗口函数处理,并在game_id,user_id都相等的行集上进行计算,得出局数,结果以下:.net
//-------------------------------------------分割线2018-07-31-----------------------------------------------code
下方评论区有大神提到能够不用窗口函数,在此要感谢大神redraiment提醒了我。当时的想法是刚学了窗口函数,还不会用,因此想实践一下,因此才用到这里的,其实更简单的方法就是大神所说,直接group by分组就好了,SQL代码以下。(果真不能为了用新知识而用新知识,仍是得按部就班,不能一口气吃成个胖子啊@-@)blog
SELECT game_id, user_id, count(*) FROM ( SELECT log_date, game_id, ( json_array_elements (points :: json) ->> 'user_id' ) AS user_id FROM game_record ) AS A GROUP BY game_id, user_id;