liusheng
2026-10-12 b25c3b5188e402695f3792ad7da53e452682cd80
ruoyi-satisfaction/src/main/resources/mapper/satisfaction/SatisfactionMapper.xml
@@ -801,6 +801,72 @@
        </if>
        group by ss.libtemplateid
    </select>
    <!-- ================================================
         「按 模板 + 问题」的答题【人数】(distinct sub_id)
         为什么需要它:/statistics 的「答题人数 / 未答题人数」必须与「发送人数」同口径(都是【人】)。
         原实现把「答题人数」取成了 selectSatisfactionFillStatByMatchedtext 的 count(*)(【明细行数】),
         而同一条 (sub_id, questiontext) 可能对应多行明细(多选项 / 重复明细),
         于是「未答题人数 = 发送人数 − 明细行数」会算成负数(实测 -120 = 15 − 135)。
         这里补一条按问题聚合的 distinct 人数查询,专供「答题人数 / 未答题人数 / 答题率」使用;
         平均分 / 最高分 / 最低分 / 各选项占比仍按明细行数统计(那些口径本来就是按行计,未改动)。
         除聚合键与 distinct 之外,from/where 与 selectSatisfactionFillStatByMatchedtext 完全一致,
         保证两者统计的是同一批数据。
         ================================================ -->
    <select id="selectSatisfactionFillPersonCountByQuestion"
            parameterType="com.ruoyi.satisfaction.domain.entity.SatisfactionStatQuery"
            resultType="java.util.Map">
        select ss.libtemplateid as libtemplateid,
               ssd.questiontext as questiontext,
               count(distinct ssd.sub_id) as cnt
        from service_subtask_detail ssd
        join service_subtask ss on ss.id = ssd.sub_id
        where ssd.del_flag = 0
        and ss.del_flag = 0
        <if test="orgid != null and orgid != ''">
            and ss.orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            and ss.campusid = #{campusid}
        </if>
        <if test="type != null and type != ''">and ss.type = #{type}</if>
        <if test="startTime != null">
            and ss.visit_time &gt;= #{startTime}
        </if>
        <if test="endTime != null">
            and ss.visit_time &lt; date_add(#{endTime}, interval 1 day)
        </if>
        <if test="libTemplateIds != null and libTemplateIds.size() > 0">
            and ss.libtemplateid IN
            <foreach collection="libTemplateIds" item="libTemplateId" open="(" separator="," close=")">
                #{libTemplateId}
            </foreach>
        </if>
        <if test="(hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0) or (deptcodes != null and deptcodes.size() > 0)">
            AND (
            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
                ss.leavehospitaldistrictcode IN
                <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="("
                         separator=","
                         close=")">
                    #{hospitaldistrictcode}
                </foreach>
            </if>
            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0 and deptcodes != null and deptcodes.size() > 0">
                OR
            </if>
            <if test="deptcodes != null and deptcodes.size() > 0">
                ss.deptcode IN
                <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                    #{deptcode}
                </foreach>
            </if>
            )
        </if>
        group by ss.libtemplateid, ssd.questiontext
    </select>
    <!-- ================================================ 重复明细清理(满意度统计前置)
         原属 ServiceSubtaskDetailMapper.xml,只有满意度统计调用(已核实),故一并搬入。
         注意 deleteRepeatDetailByIds 是【写操作】:按 id 逻辑删除重复明细(del_flag=1)。 -->