liusheng
2026-10-10 33e1839c6214ad72cc5a76ae254ce0bb542e9263
smartor/src/main/resources/mapper/smartor/ServiceSubtaskDetailMapper.xml
@@ -185,6 +185,24 @@
    </select>
    <!--
        异常问题处理情况查询(tracedeallist)的「有效填写数」:
        原来对每个 scriptid 都执行一次 selectServiceSubtaskDetailList(查回全部列再去 size),
        一个问题一次、而且整个接口会被调用两遍,几十上百个问题就是上百次大表扫描;
        这里合并成一条 group by。
        注意:为与原口径完全一致,这里不加 del_flag 条件(原 selectServiceSubtaskDetailList
        虽然 Java 里 setDelFlag("0"),但 SQL 里并没有 del_flag 过滤)。
    -->
    <select id="countDetailByScriptIds" resultType="java.util.Map">
        select scriptid as scriptid, count(*) as cnt
        from service_subtask_detail
        where scriptid in
        <foreach collection="scriptIds" item="scriptId" open="(" separator="," close=")">
            #{scriptId}
        </foreach>
        group by scriptid
    </select>
    <select id="getServiceSubtaskDetails" parameterType="com.smartor.domain.ServiceSubtaskDetailVO"
            resultType="java.util.HashMap">
        select
@@ -265,6 +283,184 @@
        <if test="questiontext != null">and questiontext = #{questiontext}</if>
    </select>
    <!--
        满意度柱状图:一次性统计本次请求全部模板的填报量。
        等价于对每个模板执行 queryFillCount(subids, questiontext),区别是:
          1) 用 join service_subtask 代替先把全部 sub_id 查回 Java 再拼 IN(...);
          2) 按 libtemplateid + questiontext + score 分组,只回传分值与条数;
          3) visit_time 改成可走索引的范围条件。
        注意:这里刻意不在 SQL 里过滤 questiontext,由 Java 按原 queryFillCount 的
        「questiontext 为 null 时不拼该条件」语义做匹配,保证结果口径完全一致。
    -->
    <select id="selectSatisfactionFillStat" parameterType="com.smartor.domain.entity.SatisfactionStatQuery"
            resultType="java.util.Map">
        select ss.libtemplateid as libtemplateid,
               ssd.questiontext as questiontext,
               ssd.score as score,
               count(*) 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, ssd.score
    </select>
    <select id="selectSatisfactionFillPersonCount" parameterType="com.smartor.domain.entity.SatisfactionStatQuery"
            resultType="java.util.Map">
        select ss.libtemplateid as libtemplateid,
               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
    </select>
    <!--
        满意度统计(statistics / statisticsByDimension):一次性统计本次请求全部问题的填报量。
        等价于对每个问题执行 queryFillCount(subids, questiontext),区别是:
          1) 用 join service_subtask 代替先把全部 sub_id 查回 Java 再拼 IN(...);
          2) 按 模板+问题+matchedtext+score 分组,只回传选项/分值与条数;
          3) targetvalue 用 min() 取该问题的一个非空选项串(同一个问题该值一致);
          4) visit_time 改成可走索引的范围条件。
        注意:这里刻意不在 SQL 里过滤 questiontext,由 Java 按原 queryFillCount 的
        「questiontext 为 null 时不拼该条件」语义做匹配,保证结果口径完全一致。
    -->
    <select id="selectSatisfactionFillStatByMatchedtext" parameterType="com.smartor.domain.entity.SatisfactionStatQuery"
            resultType="java.util.Map">
        select ss.libtemplateid as libtemplateid,
               ssd.questiontext as questiontext,
               ssd.matchedtext as matchedtext,
               ssd.score as score,
               count(*) as cnt,
               min(ssd.targetvalue) as targetvalue
        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, ssd.matchedtext, ssd.score
    </select>
    <select id="isExistServiceSubtaskDetail" resultType="com.smartor.domain.DTO.ServiceSubtaskDetailDTO">
        select id, questiontext, matchedtext, score
        from service_subtask_detail