Ver código fonte

Merge remote-tracking branch 'origin/master'

xdd 1 semana atrás
pai
commit
d10ca7acd2

+ 22 - 6
fs-service/src/main/java/com/fs/statis/mapper/ConsumptionBalanceMapper.java

@@ -100,12 +100,28 @@ public interface ConsumptionBalanceMapper {
      */
     List<DeaMemberTopTenDTO> deaMemberTopTen(AnalysisPreviewQueryDTO param);
 
-    /**
-     * 课程观看TOP10
-     * @param param 请求参数
-     * @return TOP10
-     */
-    List<CourseStatsDTO> watchCourseTopTen(AnalysisPreviewQueryDTO param);
+    // 按观看人数排序(只查观看数据)
+    List<CourseStatsDTO> watchCourseTopTenByWatch(AnalysisPreviewQueryDTO param);
+
+    // 按完成人数排序(只查观看数据)
+    List<CourseStatsDTO> watchCourseTopTenByComplete(AnalysisPreviewQueryDTO param);
+
+    // 按答题人数排序(需要关联答题表)
+    List<CourseStatsDTO> watchCourseTopTenByAnswer(AnalysisPreviewQueryDTO param);
+
+    // 按正确人数排序(需要关联答题表)
+    List<CourseStatsDTO> watchCourseTopTenByCorrect(AnalysisPreviewQueryDTO param);
+
+    // 批量补充答题数据
+    List<CourseStatsDTO> getAnswerStatsByCourseIds(@Param("courseIds") List<Long> courseIds, @Param("param") AnalysisPreviewQueryDTO param);
+
+
+//    /**
+//     * 课程观看TOP10
+//     * @param param 请求参数
+//     * @return TOP10
+//     */
+//    List<CourseStatsDTO> watchCourseTopTen(AnalysisPreviewQueryDTO param);
 
     /**
      * 奖励金额TOP10

+ 81 - 4
fs-service/src/main/java/com/fs/statis/service/impl/StatisticsCompanyServiceImpl.java

@@ -40,6 +40,8 @@ import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAdjusters;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import static com.fs.statis.StatisticsRedisConstant.*;
@@ -983,14 +985,89 @@ public class StatisticsCompanyServiceImpl implements IStatisticsCompanyService {
 
     @Override
     public List<CourseStatsDTO> watchCourseTopTen(AnalysisPreviewQueryDTO param) {
-        List<CourseStatsDTO> courseStatsDTOS = consumptionBalanceMapper.watchCourseTopTen(param);
-        for (CourseStatsDTO courseStatsDTO : courseStatsDTOS) {
+//        List<CourseStatsDTO> courseStatsDTOS = consumptionBalanceMapper.watchCourseTopTen(param);
+//        for (CourseStatsDTO courseStatsDTO : courseStatsDTOS) {
+//            String courseName = fsUserCourseCacheService.selectCourseNameByCourseId(courseStatsDTO.getCourseId());
+//            if(StringUtils.isNotBlank(courseName)){
+//                courseStatsDTO.setCourseName(courseName);
+//            }
+//        }
+//        return courseStatsDTOS;
+        //2025.11.07 优化
+        // 1. 根据统计类型获取基础数据
+        List<CourseStatsDTO> result = getBaseCourseStats(param);
+
+        // 2. 如果查询的是观看或完成数据,需要补充答题数据
+        if (param.getStatisticalType() == 0 || param.getStatisticalType() == 1) {
+            supplementAnswerData(result, param);
+        }
+
+        // 3. 设置课程名称
+        setCourseNames(result);
+
+        return result;
+    }
+
+    /**
+     * 获取基础课程统计数据
+     */
+    private List<CourseStatsDTO> getBaseCourseStats(AnalysisPreviewQueryDTO param) {
+        Integer statisticalType = param.getStatisticalType();
+        switch (statisticalType) {
+            case 0: // 观看人数
+                return consumptionBalanceMapper.watchCourseTopTenByWatch(param);
+            case 1: // 完成人数
+                return consumptionBalanceMapper.watchCourseTopTenByComplete(param);
+            case 2: // 答题人数
+                return consumptionBalanceMapper.watchCourseTopTenByAnswer(param);
+            case 3: // 正确人数
+                return consumptionBalanceMapper.watchCourseTopTenByCorrect(param);
+            default:
+                return consumptionBalanceMapper.watchCourseTopTenByWatch(param);
+        }
+    }
+
+    /**
+     * 补充答题数据(针对观看和完成统计)
+     */
+    private void supplementAnswerData(List<CourseStatsDTO> result, AnalysisPreviewQueryDTO param) {
+        if (result == null || result.isEmpty()) {
+            return;
+        }
+
+        // 提取课程ID列表
+        List<Long> courseIds = result.stream()
+                .map(CourseStatsDTO::getCourseId)
+                .collect(Collectors.toList());
+
+        // 批量查询答题数据
+        List<CourseStatsDTO> answerStats = consumptionBalanceMapper.getAnswerStatsByCourseIds(courseIds, param);
+
+        // 构建课程ID到答题数据的映射
+        Map<Long, CourseStatsDTO> answerMap = answerStats.stream()
+                .collect(Collectors.toMap(CourseStatsDTO::getCourseId, Function.identity()));
+
+        // 合并答题数据到结果中
+        for (CourseStatsDTO dto : result) {
+            CourseStatsDTO answerStat = answerMap.get(dto.getCourseId());
+            if (answerStat != null) {
+                dto.setAnswerUserCount(answerStat.getAnswerUserCount());
+                dto.setCorrectUserCount(answerStat.getCorrectUserCount());
+            }
+            // 如果没有答题数据,保持原来的0值
+        }
+    }
+
+    /**
+     * 设置课程名称
+     */
+    private void setCourseNames(List<CourseStatsDTO> result) {
+        for (CourseStatsDTO courseStatsDTO : result) {
             String courseName = fsUserCourseCacheService.selectCourseNameByCourseId(courseStatsDTO.getCourseId());
-            if(StringUtils.isNotBlank(courseName)){
+            if (StringUtils.isNotBlank(courseName)) {
                 courseStatsDTO.setCourseName(courseName);
             }
         }
-        return courseStatsDTOS;
     }
 
     @Override

+ 79 - 4
fs-service/src/main/java/com/fs/statis/service/impl/StatisticsServiceImpl.java

@@ -46,6 +46,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import com.fs.statistics.dto.WatchCourseStatisticsDTO;
 
@@ -897,14 +898,88 @@ public class StatisticsServiceImpl implements IStatisticsService {
 
     @Override
     public List<CourseStatsDTO> watchCourseTopTen(AnalysisPreviewQueryDTO param) {
-        List<CourseStatsDTO> courseStatsDTOS = consumptionBalanceMapper.watchCourseTopTen(param);
-        for (CourseStatsDTO courseStatsDTO : courseStatsDTOS) {
+//        List<CourseStatsDTO> courseStatsDTOS = consumptionBalanceMapper.watchCourseTopTen(param);
+//        for (CourseStatsDTO courseStatsDTO : courseStatsDTOS) {
+//            String courseName = fsUserCourseCacheService.selectCourseNameByCourseId(courseStatsDTO.getCourseId());
+//            if(StringUtils.isNotBlank(courseName)){
+//                courseStatsDTO.setCourseName(courseName);
+//            }
+//        }
+//        return courseStatsDTOS;
+        // 1. 根据统计类型获取基础数据
+        List<CourseStatsDTO> result = getBaseCourseStats(param);
+
+        // 2. 如果查询的是观看或完成数据,需要补充答题数据
+        if (param.getStatisticalType() == 0 || param.getStatisticalType() == 1) {
+            supplementAnswerData(result, param);
+        }
+
+        // 3. 设置课程名称
+        setCourseNames(result);
+
+        return result;
+    }
+
+    /**
+     * 获取基础课程统计数据
+     */
+    private List<CourseStatsDTO> getBaseCourseStats(AnalysisPreviewQueryDTO param) {
+        Integer statisticalType = param.getStatisticalType();
+        switch (statisticalType) {
+            case 0: // 观看人数
+                return consumptionBalanceMapper.watchCourseTopTenByWatch(param);
+            case 1: // 完成人数
+                return consumptionBalanceMapper.watchCourseTopTenByComplete(param);
+            case 2: // 答题人数
+                return consumptionBalanceMapper.watchCourseTopTenByAnswer(param);
+            case 3: // 正确人数
+                return consumptionBalanceMapper.watchCourseTopTenByCorrect(param);
+            default:
+                return consumptionBalanceMapper.watchCourseTopTenByWatch(param);
+        }
+    }
+
+    /**
+     * 补充答题数据(针对观看和完成统计)
+     */
+    private void supplementAnswerData(List<CourseStatsDTO> result, AnalysisPreviewQueryDTO param) {
+        if (result == null || result.isEmpty()) {
+            return;
+        }
+
+        // 提取课程ID列表
+        List<Long> courseIds = result.stream()
+                .map(CourseStatsDTO::getCourseId)
+                .collect(Collectors.toList());
+
+        // 批量查询答题数据
+        List<CourseStatsDTO> answerStats = consumptionBalanceMapper.getAnswerStatsByCourseIds(courseIds, param);
+
+        // 构建课程ID到答题数据的映射
+        Map<Long, CourseStatsDTO> answerMap = answerStats.stream()
+                .collect(Collectors.toMap(CourseStatsDTO::getCourseId, Function.identity()));
+
+        // 合并答题数据到结果中
+        for (CourseStatsDTO dto : result) {
+            CourseStatsDTO answerStat = answerMap.get(dto.getCourseId());
+            if (answerStat != null) {
+                dto.setAnswerUserCount(answerStat.getAnswerUserCount());
+                dto.setCorrectUserCount(answerStat.getCorrectUserCount());
+            }
+            // 如果没有答题数据,保持原来的0值
+        }
+    }
+
+    /**
+     * 设置课程名称
+     */
+    private void setCourseNames(List<CourseStatsDTO> result) {
+        for (CourseStatsDTO courseStatsDTO : result) {
             String courseName = fsUserCourseCacheService.selectCourseNameByCourseId(courseStatsDTO.getCourseId());
-            if(StringUtils.isNotBlank(courseName)){
+            if (StringUtils.isNotBlank(courseName)) {
                 courseStatsDTO.setCourseName(courseName);
             }
         }
-        return courseStatsDTOS;
     }
 
     @Override

+ 1 - 1
fs-service/src/main/resources/application-druid-knt2.yml

@@ -9,7 +9,7 @@ spring:
         # 端口,默认为6379
         port: 6379
         # 数据库索引
-        database: 2
+        database: 1
         # 密码
         password: Ylrztek250218!3@.
         # 连接超时时间

+ 11 - 5
fs-service/src/main/resources/mapper/course/FsCourseTrafficLogMapper.xml

@@ -60,7 +60,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_course_traffic_log
         <where>
-            DATE(create_time) = CURDATE()
+            <!-- DATE(create_time) = CURDATE() -->
+            create_time >= CURDATE()
+            AND create_time &lt; CURDATE() + INTERVAL 1 DAY
             <if test="companyId != null">
                 AND company_id = ${companyId}
             </if>
@@ -85,8 +87,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_course_traffic_log
         <where>
-            YEAR(create_time) = YEAR(CURDATE())
-            AND MONTH(create_time) = MONTH(CURDATE())
+            <!-- YEAR(create_time) = YEAR(CURDATE()) -->
+            <!-- AND MONTH(create_time) = MONTH(CURDATE()) -->
+            create_time >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
+            AND create_time &lt; DATE_FORMAT(CURDATE() + INTERVAL 1 MONTH, '%Y-%m-01')
             <if test="companyId != null">
                 AND company_id = ${companyId}
             </if>
@@ -114,8 +118,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
             fs_course_traffic_log
         WHERE
-            YEAR(create_time) = YEAR(CURDATE())
-          AND MONTH(create_time) = MONTH(CURDATE())
+        <!-- YEAR(create_time) = YEAR(CURDATE()) -->
+        <!-- AND MONTH(create_time) = MONTH(CURDATE()) -->
+        create_time >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
+        AND create_time &lt; DATE_FORMAT(CURDATE() + INTERVAL 1 MONTH, '%Y-%m-01')
     </select>
 
     <insert id="insertFsCourseTrafficLog" parameterType="FsCourseTrafficLog" useGeneratedKeys="true" keyProperty="logId">

+ 174 - 42
fs-service/src/main/resources/mapper/statis/ConsumptionBalanceMapper.xml

@@ -168,14 +168,16 @@
     </select>
     <select id="watchEndPlayTrend" resultType="com.fs.statis.dto.WatchEndPlayTrendDTO">
         SELECT
---             今日/昨日 小时
-            <if test="type == 0 or type == 1">
+        <choose>
+            <!-- 按小时分组 -->
+            <when test="type == 0 or type == 1">
                 DATE_FORMAT(create_time, '%H') AS start_date,
-            </if>
---                 本周/本月/上月 天
-            <if test="type == 2 or type == 3 or type == 4">
+            </when>
+            <!-- 按天分组 -->
+            <when test="type == 2 or type == 3 or type == 4">
                 DATE_FORMAT(create_time, '%Y-%m-%d') AS start_date,
-            </if>
+            </when>
+        </choose>
         COUNT(DISTINCT user_id) AS watch_user_count,
         COUNT(DISTINCT CASE WHEN log_type = 2 THEN user_id END) AS completed_user_count
         FROM
@@ -192,7 +194,10 @@
             </if>
         </where>
         GROUP BY
-        start_date
+        <choose>
+            <when test="type == 0 or type == 1">DATE_FORMAT(create_time, '%H')</when>
+            <when test="type == 2 or type == 3 or type == 4">DATE_FORMAT(create_time, '%Y-%m-%d')</when>
+        </choose>
         ORDER BY
         start_date
     </select>
@@ -224,50 +229,177 @@
         GROUP BY company_id
         limit 10
     </select>
-    <select id="watchCourseTopTen" resultType="com.fs.statis.dto.CourseStatsDTO">
+<!--    <select id="watchCourseTopTen" resultType="com.fs.statis.dto.CourseStatsDTO">-->
+<!--        SELECT-->
+<!--        w.course_id AS course_id,-->
+<!--        COUNT(DISTINCT w.user_id) AS watch_user_count,-->
+<!--        COUNT(DISTINCT CASE WHEN w.log_type = 2 THEN w.user_id END) AS completed_user_count,-->
+<!--        COUNT(DISTINCT a.user_id) AS answer_user_count,-->
+<!--        COUNT(DISTINCT CASE WHEN a.is_right = 1 THEN a.user_id END) AS correct_user_count-->
+<!--        FROM-->
+<!--        fs_course_watch_log w-->
+<!--        LEFT JOIN-->
+<!--        fs_course_answer_logs a ON w.video_id = a.video_id AND w.user_id = a.user_id-->
+<!--        <where>-->
+<!--            <if test="startTime != null">-->
+<!--                w.create_time <![CDATA[>=]]> #{startTime}-->
+<!--            </if>-->
+<!--            <if test="endTime != null">-->
+<!--                AND w.create_time <![CDATA[<]]> #{endTime}-->
+<!--            </if>-->
+<!--            <if test="userType != null">-->
+<!--                AND send_type = ${userType}-->
+<!--            </if>-->
+<!--            <if test="companyId != null">-->
+<!--                AND w.company_id = ${companyId}-->
+<!--            </if>-->
+<!--        </where>-->
+<!--        GROUP BY-->
+<!--        w.course_id-->
+<!--        ORDER BY-->
+<!--            &#45;&#45; 观看人数-->
+<!--            <if test="statisticalType == 0">-->
+<!--                COUNT(DISTINCT w.user_id)-->
+<!--            </if>-->
+<!--            <if test="statisticalType == 1">-->
+<!--                COUNT(DISTINCT CASE WHEN w.log_type = 2 THEN w.user_id END)-->
+<!--            </if>-->
+<!--            <if test="statisticalType == 2">-->
+<!--                COUNT(DISTINCT a.user_id)-->
+<!--            </if>-->
+<!--            <if test="statisticalType == 3">-->
+<!--                COUNT(DISTINCT CASE WHEN a.is_right = 1 THEN a.user_id END)-->
+<!--            </if>-->
+<!--        ${sort}-->
+<!--        LIMIT 10-->
+<!--    </select>-->
+
+    <!-- 1. 按观看人数排序 -->
+    <select id="watchCourseTopTenByWatch" resultType="com.fs.statis.dto.CourseStatsDTO">
+        SELECT
+        course_id AS courseId,
+        COUNT(DISTINCT user_id) AS watch_user_count,
+        COUNT(DISTINCT CASE WHEN log_type = 2 THEN user_id END) AS completed_user_count,
+        0 AS answer_user_count,
+        0 AS correct_user_count
+        FROM fs_course_watch_log
+        <where>
+            <if test="startTime != null">create_time <![CDATA[>=]]> #{startTime}</if>
+            <if test="endTime != null">AND create_time <![CDATA[<]]> #{endTime}</if>
+            <if test="userType != null">AND send_type = #{userType}</if>
+            <if test="companyId != null">AND company_id = #{companyId}</if>
+        </where>
+        GROUP BY course_id
+        ORDER BY watch_user_count
+        <choose>
+            <when test="sort != null and sort == 'DESC'">DESC</when>
+            <otherwise>ASC</otherwise>
+        </choose>
+        LIMIT 10
+    </select>
+
+    <!-- 2. 按完成人数排序 -->
+    <select id="watchCourseTopTenByComplete" resultType="com.fs.statis.dto.CourseStatsDTO">
         SELECT
-        w.course_id AS course_id,
+        course_id AS courseId,
+        COUNT(DISTINCT user_id) AS watch_user_count,
+        COUNT(DISTINCT CASE WHEN log_type = 2 THEN user_id END) AS completed_user_count,
+        0 AS answer_user_count,
+        0 AS correct_user_count
+        FROM fs_course_watch_log
+        <where>
+            <if test="startTime != null">create_time <![CDATA[>=]]> #{startTime}</if>
+            <if test="endTime != null">AND create_time <![CDATA[<]]> #{endTime}</if>
+            <if test="userType != null">AND send_type = #{userType}</if>
+            <if test="companyId != null">AND company_id = #{companyId}</if>
+        </where>
+        GROUP BY course_id
+        ORDER BY completed_user_count
+        <choose>
+            <when test="sort != null and sort == 'DESC'">DESC</when>
+            <otherwise>ASC</otherwise>
+        </choose>
+        LIMIT 10
+    </select>
+
+    <!-- 3. 按答题人数排序 -->
+    <select id="watchCourseTopTenByAnswer" resultType="com.fs.statis.dto.CourseStatsDTO">
+        SELECT
+        w.course_id AS courseId,
         COUNT(DISTINCT w.user_id) AS watch_user_count,
         COUNT(DISTINCT CASE WHEN w.log_type = 2 THEN w.user_id END) AS completed_user_count,
         COUNT(DISTINCT a.user_id) AS answer_user_count,
         COUNT(DISTINCT CASE WHEN a.is_right = 1 THEN a.user_id END) AS correct_user_count
-        FROM
-        fs_course_watch_log w
-        LEFT JOIN
-        fs_course_answer_logs a ON w.video_id = a.video_id AND w.user_id = a.user_id
+        FROM fs_course_watch_log w
+        LEFT JOIN fs_course_answer_logs a ON w.video_id = a.video_id AND w.user_id = a.user_id
         <where>
-            <if test="startTime != null">
-                w.create_time <![CDATA[>=]]> #{startTime}
-            </if>
-            <if test="endTime != null">
-                AND w.create_time <![CDATA[<]]> #{endTime}
-            </if>
-            <if test="userType != null">
-                AND send_type = ${userType}
-            </if>
-            <if test="companyId != null">
-                AND w.company_id = ${companyId}
-            </if>
+            <if test="startTime != null">w.create_time <![CDATA[>=]]> #{startTime}</if>
+            <if test="endTime != null">AND w.create_time <![CDATA[<]]> #{endTime}</if>
+            <if test="userType != null">AND w.send_type = #{userType}</if>
+            <if test="companyId != null">AND w.company_id = #{companyId}</if>
+<!--            <if test="startTime != null">AND a.create_time <![CDATA[>=]]> #{startTime}</if> -->
+<!--            <if test="endTime != null">AND a.create_time <![CDATA[<]]> #{endTime}</if> -->
         </where>
-        GROUP BY
-        w.course_id
-        ORDER BY
-            -- 观看人数
-            <if test="statisticalType == 0">
-                COUNT(DISTINCT w.user_id)
-            </if>
-            <if test="statisticalType == 1">
-                COUNT(DISTINCT CASE WHEN w.log_type = 2 THEN w.user_id END)
-            </if>
-            <if test="statisticalType == 2">
-                COUNT(DISTINCT a.user_id)
-            </if>
-            <if test="statisticalType == 3">
-                COUNT(DISTINCT CASE WHEN a.is_right = 1 THEN a.user_id END)
-            </if>
-        ${sort}
+        GROUP BY w.course_id
+        ORDER BY answer_user_count
+        <choose>
+            <when test="sort != null and sort == 'DESC'">DESC</when>
+            <otherwise>ASC</otherwise>
+        </choose>
+        LIMIT 10
+    </select>
+
+    <!-- 4. 按正确人数排序 -->
+    <select id="watchCourseTopTenByCorrect" resultType="com.fs.statis.dto.CourseStatsDTO">
+        SELECT
+        w.course_id AS courseId,
+        COUNT(DISTINCT w.user_id) AS watch_user_count,
+        COUNT(DISTINCT CASE WHEN w.log_type = 2 THEN w.user_id END) AS completed_user_count,
+        COUNT(DISTINCT a.user_id) AS answer_user_count,
+        COUNT(DISTINCT CASE WHEN a.is_right = 1 THEN a.user_id END) AS correct_user_count
+        FROM fs_course_watch_log w
+        LEFT JOIN fs_course_answer_logs a ON w.video_id = a.video_id AND w.user_id = a.user_id
+        <where>
+            <if test="startTime != null">w.create_time <![CDATA[>=]]> #{startTime}</if>
+            <if test="endTime != null">AND w.create_time <![CDATA[<]]> #{endTime}</if>
+            <if test="userType != null">AND w.send_type = #{userType}</if>
+            <if test="companyId != null">AND w.company_id = #{companyId}</if>
+            <if test="startTime != null">AND a.create_time <![CDATA[>=]]> #{startTime}</if>
+            <if test="endTime != null">AND a.create_time <![CDATA[<]]> #{endTime}</if>
+        </where>
+        GROUP BY w.course_id
+        ORDER BY correct_user_count
+        <choose>
+            <when test="sort != null and sort == 'DESC'">DESC</when>
+            <otherwise>ASC</otherwise>
+        </choose>
         LIMIT 10
     </select>
+
+    <!-- 5. 批量补充答题数据 -->
+    <select id="getAnswerStatsByCourseIds" resultType="com.fs.statis.dto.CourseStatsDTO">
+        SELECT
+        w.course_id AS courseId,
+        COUNT(DISTINCT a.user_id) AS answer_user_count,
+        COUNT(DISTINCT CASE WHEN a.is_right = 1 THEN a.user_id END) AS correct_user_count
+        FROM fs_course_answer_logs a
+        INNER JOIN fs_course_watch_log w ON a.video_id = w.video_id AND a.user_id = w.user_id
+        <where>
+            w.course_id IN
+            <foreach collection="courseIds" item="courseId" open="(" close=")" separator=",">
+                #{courseId}
+            </foreach>
+            <if test="param.startTime != null">AND w.create_time <![CDATA[>=]]> #{param.startTime}</if>
+            <if test="param.endTime != null">AND w.create_time <![CDATA[<]]> #{param.endTime}</if>
+            <if test="param.userType != null">AND w.send_type = #{param.userType}</if>
+            <if test="param.companyId != null">AND w.company_id = #{param.companyId}</if>
+            <if test="param.startTime != null">AND a.create_time <![CDATA[>=]]> #{param.startTime}</if>
+            <if test="param.endTime != null">AND a.create_time <![CDATA[<]]> #{param.endTime}</if>
+        </where>
+        GROUP BY w.course_id
+    </select>
+
+
     <select id="rewardMoneyTopTen" resultType="com.fs.statis.dto.RewardMoneyTopTenDTO">
         SELECT
             -- 按公司