package cn.iocoder.yudao.module.im.dal.mysql.statistics; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import java.time.LocalDateTime; import java.util.List; import java.util.Map; /** * IM 数据看板 Mapper *

* 独立于业务 Mapper:所有统计 SQL 集中在此,仅服务于 manager 看板,不被其它业务调用,保持各业务 Mapper / Service 不受统计需求污染。 * * @author 芋道源码 */ @Mapper public interface ImStatisticsManagerMapper { String NORMAL_MESSAGE_CONDITION = "type IN (101,102,103,104,105,107,108,115,125) AND status <> 2"; // ==================== 用户 ==================== /** * 用户总数(system_users) */ @Select("SELECT COUNT(*) FROM system_users WHERE deleted = 0") Long selectTotalUserCount(); /** * 区间内新增用户数 */ @Select("SELECT COUNT(*) FROM system_users " + "WHERE deleted = 0 AND create_time >= #{beginTime} AND create_time < #{endTime}") Long selectNewUserCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内活跃用户数:私聊或群聊发过消息的去重用户数 */ @Select("SELECT COUNT(DISTINCT user_id) FROM (" + " SELECT sender_id AS user_id FROM im_private_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + " UNION ALL " + " SELECT sender_id AS user_id FROM im_group_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t") Long selectActiveUserCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内每日新增用户数(按天分组) * * @return [{date: "yyyy-MM-dd", count: 123}, ...] */ @Select("SELECT DATE(create_time) AS date, COUNT(*) AS count FROM system_users " + "WHERE deleted = 0 AND create_time >= #{beginTime} AND create_time < #{endTime} " + "GROUP BY DATE(create_time)") List> selectNewUserDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内每日活跃用户数(按天分组、跨私聊+群聊去重) */ @Select("SELECT day AS date, COUNT(DISTINCT user_id) AS count FROM (" + " SELECT DATE(send_time) AS day, sender_id AS user_id FROM im_private_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + " UNION ALL " + " SELECT DATE(send_time) AS day, sender_id AS user_id FROM im_group_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY day") List> selectActiveUserDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); // ==================== 群 ==================== /** * 当前有效群总数 */ @Select("SELECT COUNT(*) FROM im_group WHERE deleted = 0 AND status = 0") Long selectTotalGroupCount(); /** * 区间内新建群数 */ @Select("SELECT COUNT(*) FROM im_group " + "WHERE deleted = 0 AND create_time >= #{beginTime} AND create_time < #{endTime}") Long selectNewGroupCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 群规模分布(按群成员数分桶) * * @return [{range: "1-9 人", count: 123}, ...] */ @Select("SELECT " + " CASE " + " WHEN cnt < 10 THEN '1-9 人' " + " WHEN cnt < 50 THEN '10-49 人' " + " WHEN cnt < 200 THEN '50-199 人' " + " ELSE '200+ 人' " + " END AS `range`, COUNT(*) AS count " + "FROM (" + " SELECT g.id, COUNT(m.id) AS cnt " + " FROM im_group g " + " LEFT JOIN im_group_member m ON m.group_id = g.id AND m.status = 0 AND m.deleted = 0 " + " WHERE g.deleted = 0 AND g.status = 0 " + " GROUP BY g.id" + ") t " + "GROUP BY `range`") List> selectGroupSizeDistribution(); // ==================== 消息 ==================== /** * 区间内私聊消息数 */ @Select("SELECT COUNT(*) FROM im_private_message " + "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}") Long selectPrivateMessageCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内群聊消息数 */ @Select("SELECT COUNT(*) FROM im_group_message " + "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}") Long selectGroupMessageCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内每日私聊消息数(按天分组) */ @Select("SELECT DATE(send_time) AS date, COUNT(*) AS count FROM im_private_message " + "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime} " + "GROUP BY DATE(send_time)") List> selectPrivateMessageDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内每日群聊消息数(按天分组) */ @Select("SELECT DATE(send_time) AS date, COUNT(*) AS count FROM im_group_message " + "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime} " + "GROUP BY DATE(send_time)") List> selectGroupMessageDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内内容类型分布(私聊+群聊合并) * * @return [{type: 0, count: 123}, ...] */ @Select("SELECT type, COUNT(*) AS count FROM (" + " SELECT type FROM im_private_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + " UNION ALL " + " SELECT type FROM im_group_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY type") List> selectMessageTypeDistribution(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); /** * 区间内 TOP 发送者(私聊+群聊合并,按消息数倒序) * * @return [{userId: 1024, messageCount: 1500}, ...] */ @Select("SELECT user_id AS userId, COUNT(*) AS messageCount FROM (" + " SELECT sender_id AS user_id FROM im_private_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + " UNION ALL " + " SELECT sender_id AS user_id FROM im_group_message " + " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY user_id ORDER BY messageCount DESC LIMIT #{limit}") List> selectTopSenders(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime, @Param("limit") int limit); }