liusheng
5 天以前 cc479e6a056785103996cc7ea67dbd5faa3e800e
ruoyi-inhospvisit/src/main/resources/mapper/inhospvisit/PatMedInhospMapper.xml
@@ -163,6 +163,148 @@
        from pat_med_inhosp
    </sql>
    <sql id="selectPatMedInhospListFromWhere">
        pat_med_inhosp b
        JOIN
        pat_archive a ON a.id = b.patid
        where 1=1
        <!--
          del_flag 必须用字符串常量比较:它取值是 '0'/'1'(char 列)。
          写成 del_flag = 0 时 MySQL 会把【列】按 DOUBLE 隐式转换,该条件就只是过滤、
          不能用来定位索引;而 b.del_flag 正是 idx_inhosp_optimize / idx_pmi_del_org_end
          的首列 —— 数字写法等于把索引首列白给。
          同一结论见 sql/sltdMydTotalByDimension_index_20260924.sql 第 117-134 行。
          (列是 int 时写 '0' 也安全:转换发生在常量侧,索引照样可用。)
        -->
        AND a.del_flag = '0'
        AND b.del_flag = '0'
        AND a.idcardno IS NOT NULL
        <if test="inhospid != null">and b.inhospid = #{inhospid}</if>
        <if test="startOutHospTime != null ">and date_format(b.endtime,'%y%m%d') &gt;=
            date_format(#{startOutHospTime},'%y%m%d')
        </if>
        <if test="endOutHospTime != null ">and date_format(b.endtime,'%y%m%d') &lt;=
            date_format(#{endOutHospTime},'%y%m%d')
        </if>
        <if test="startInHospTime != null ">and date_format(b.starttime,'%y%m%d') &gt;=
            date_format(#{startInHospTime},'%y%m%d')
        </if>
        <if test="endInHospTime != null ">and date_format(b.starttime,'%y%m%d') &lt;=
            date_format(#{endInHospTime},'%y%m%d')
        </if>
        <if test="hospitalname != null  and hospitalname != ''">and hospitalname like concat('%', #{hospitalname},
            '%')
        </if>
        <if test="patname != null  and patname != ''">and patname like concat('%', #{patname}, '%')</if>
        <if test="hospitaldistrictname != null  and hospitaldistrictname != ''">and hospitaldistrictname like
            concat('%', #{hospitaldistrictname}, '%')
        </if>
        <if test="endtime != null ">and b.endtime = #{endtime}</if>
        <if test="bedNo != null ">and b.bed_no = #{bedNo}</if>
        <if test="inhospMydFlag != null ">and b.inhosp_myd_flag = #{inhospMydFlag}</if>
        <if test="managementDoctor != null ">and b.management_doctor = #{managementDoctor}</if>
        <if test="managementDoctorCode != null ">and b.management_doctor_code = #{managementDoctorCode}</if>
        <if test="inhospno != null ">and b.inhospno = #{inhospno}</if>
        <if test="fuflag != null ">and b.fuflag = #{fuflag}</if>
        <if test="orgid != null ">and b.orgid = #{orgid}</if>
        <if test="campusid != null ">and b.campusid = #{campusid}</if>
        <if test="serialnum != null ">and b.serialnum = #{serialnum}</if>
        <if test="endtime != null ">and b.endtime = #{endtime}</if>
        <if test="patno != null ">and b.patno = #{patno}</if>
        <if test="nurseId != null ">and b.nurse_id = #{nurseId}</if>
        <if test="nurseName != null and nurseName != ''">and b.nurse_name = #{nurseName}</if>
        <if test="deptcheckFlag != null ">and b.deptcheck_flag = #{deptcheckFlag}</if>
        <if test="scheduleCheckFlag != null ">and b.schedulecheck_flag = #{scheduleCheckFlag}</if>
        <if test="wardcheckFlag != null ">and b.wardcheck_flag = #{wardcheckFlag}</if>
        <if test="inDeptcheckFlag != null ">and b.in_deptcheck_flag = #{inDeptcheckFlag}</if>
        <if test="inWardcheckFlag != null ">and b.in_wardcheck_flag = #{inWardcheckFlag}</if>
        <if test="diagcheckFlag != null ">and b.diagcheck_flag = #{diagcheckFlag}</if>
        <if test="encounterSourceId != null ">and b.encounter_source_id = #{encounterSourceId}</if>
        <if test="importanceFlagCode != null ">and b.importance_flag_code = #{importanceFlagCode}</if>
        <if test="emergencyLevelCode != null ">and b.emergency_level_code = #{emergencyLevelCode}</if>
        <!--
          在院(cry=0):两个条件都要。
          ① b.endtime is null —— 原 XML 就有,保持不动;
          ② b.inhospstate = '0' —— 迁出前由 PatMedInhospServiceImpl 补(cry=0 时
             setInhospstate("0")),迁到本模块后这条链直连 Mapper,这句就丢了。
          为什么必须补回来(不只是"恢复原行为",也是性能问题):
            · 索引 idx_inhosp_optimize / idx_pmi_del_org_state_end 的前三列是
              (del_flag, orgid, inhospstate),只有三个等值条件齐了才能精确定位"在院"那几千行;
              少了 inhospstate,就只能用到 (del_flag, orgid) 前缀 = 该机构【全部历史住院记录】,
              再加上后面的 ORDER BY/GROUP BY,实测就是 4~5 秒的来源。
            · cry=1/2/3 本来就是按 inhospstate 判的,只有 cry=0 用 endtime 判 —— 补齐后才对称。
          为什么加 inhospstate == null 这个前提:调用方若已显式指定 inhospstate,就别和它打架
          (否则 cry=0 + inhospstate='2' 会变成"和自身矛盾"的空结果)。
        -->
        <if test="cry != null and cry == 0 ">and b.endtime is null</if>
        <if test="cry != null and cry == 0 and inhospstate == null ">and b.inhospstate = '0'</if>
        <!-- 同 del_flag:inhospstate 是取值范围 '0'~'3' 的字符列,必须用字符串常量,
             否则索引上用不到这个等值条件(出院/转科/预入院 三个视图走的就是这三行) -->
        <if test="cry != null and cry == 1 ">and b.inhospstate='1'</if>
        <if test="cry != null and cry == 2 ">and b.inhospstate='2'</if>
        <if test="cry != null and cry == 3 ">and b.inhospstate='3'</if>
        <if test="inhospstate != null ">and b.inhospstate = #{inhospstate}</if>
        <if test="schemestatus != null ">and b.schemestatus = #{schemestatus}</if>
        <if test="outWayId != null ">and b.out_way_id = #{outWayId}</if>
        <if test="outWayName != null ">and b.out_way_name = #{outWayName}</if>
        <if test="leaveldeptcode != null ">and b.leaveldeptcode = #{leaveldeptcode}</if>
        <if test="leavediagname != null  and leavediagname != ''">and b.leavediagname like concat('%',
            #{leavediagname}, '%')
        </if>
        <if test="drname != null  and drname != ''">and b.drname like concat('%', #{drname}, '%')</if>
        <if test="leaveldeptname != null  and leaveldeptname != ''">and b.leaveldeptname like concat('%',
            #{leaveldeptname}, '%')
        </if>
        <if test="deptname != null  and deptname != ''">and b.deptname like concat('%',
            #{deptname}, '%')
        </if>
        <if test="patid != null  and patid != ''">and a.id =#{patid}
        </if>
        <if test="leavehospitaldistrictname != null  and leavehospitaldistrictname != ''">and
            b.leavehospitaldistrictname like concat('%', #{leavehospitaldistrictname}, '%')
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size()>0">
            AND b.leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                     close=")">
                #{leavehospitaldistrictcode}
            </foreach>
        </if>
        <if test="hospitaldistrictcodeList != null and hospitaldistrictcodeList.size()>0">
            AND b.hospitaldistrictcode IN
            <foreach collection="hospitaldistrictcodeList" item="hospitaldistrictcode" open="(" separator=","
                     close=")">
                #{hospitaldistrictcode}
            </foreach>
        </if>
        <if test="leaveldeptcodes != null and leaveldeptcodes.size()>0">
            AND b.leaveldeptcode IN
            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                     close=")">
                #{leaveldeptcode}
            </foreach>
        </if>
        <if test="deptcodeList != null and deptcodeList.size()>0">
            AND b.deptcode IN
            <foreach collection="deptcodeList" item="deptcode" open="(" separator=","
                     close=")">
                #{deptcode}
            </foreach>
        </if>
        <if test="icd10codeList != null and icd10codeList.size()>0">
            AND b.leaveicd10code IN
            <foreach collection="icd10codeList" item="icd10code" open="(" separator=","
                     close=")">
                #{icd10code}
            </foreach>
        </if>
        <if test="medicalCode != null and medicalCode != ''">and b.medical_code = #{medicalCode}</if>
        <if test="medicalName != null and medicalName != ''">and b.medical_name = #{medicalName}</if>
        <if test="medicalCompany != null and medicalCompany != ''">and b.medical_company = #{medicalCompany}</if>
    </sql>
    <select id="selectPatMedInhospList" parameterType="com.ruoyi.inhospvisit.domain.PatMedInhosp" resultMap="PatMedInhospResult">
        select a.age AS age,
        a.telcode as telcode,
@@ -239,120 +381,7 @@
        b.medical_company,
        a.idcardno
        FROM
        pat_med_inhosp b
        JOIN
        pat_archive a ON a.id = b.patid
        where 1=1
        AND a.del_flag = 0
        AND b.del_flag = 0
        AND a.idcardno IS NOT NULL
        <if test="inhospid != null">and b.inhospid = #{inhospid}</if>
        <if test="startOutHospTime != null ">and date_format(b.endtime,'%y%m%d') &gt;=
            date_format(#{startOutHospTime},'%y%m%d')
        </if>
        <if test="endOutHospTime != null ">and date_format(b.endtime,'%y%m%d') &lt;=
            date_format(#{endOutHospTime},'%y%m%d')
        </if>
        <if test="startInHospTime != null ">and date_format(b.starttime,'%y%m%d') &gt;=
            date_format(#{startInHospTime},'%y%m%d')
        </if>
        <if test="endInHospTime != null ">and date_format(b.starttime,'%y%m%d') &lt;=
            date_format(#{endInHospTime},'%y%m%d')
        </if>
        <if test="hospitalname != null  and hospitalname != ''">and hospitalname like concat('%', #{hospitalname},
            '%')
        </if>
        <if test="patname != null  and patname != ''">and patname like concat('%', #{patname}, '%')</if>
        <if test="hospitaldistrictname != null  and hospitaldistrictname != ''">and hospitaldistrictname like
            concat('%', #{hospitaldistrictname}, '%')
        </if>
        <if test="endtime != null ">and b.endtime = #{endtime}</if>
        <if test="bedNo != null ">and b.bed_no = #{bedNo}</if>
        <if test="inhospMydFlag != null ">and b.inhosp_myd_flag = #{inhospMydFlag}</if>
        <if test="managementDoctor != null ">and b.management_doctor = #{managementDoctor}</if>
        <if test="managementDoctorCode != null ">and b.management_doctor_code = #{managementDoctorCode}</if>
        <if test="inhospno != null ">and b.inhospno = #{inhospno}</if>
        <if test="fuflag != null ">and b.fuflag = #{fuflag}</if>
        <if test="orgid != null ">and b.orgid = #{orgid}</if>
        <if test="campusid != null ">and b.campusid = #{campusid}</if>
        <if test="serialnum != null ">and b.serialnum = #{serialnum}</if>
        <if test="endtime != null ">and b.endtime = #{endtime}</if>
        <if test="patno != null ">and b.patno = #{patno}</if>
        <if test="nurseId != null ">and b.nurse_id = #{nurseId}</if>
        <if test="nurseName != null and nurseName != ''">and b.nurse_name = #{nurseName}</if>
        <if test="deptcheckFlag != null ">and b.deptcheck_flag = #{deptcheckFlag}</if>
        <if test="scheduleCheckFlag != null ">and b.schedulecheck_flag = #{scheduleCheckFlag}</if>
        <if test="wardcheckFlag != null ">and b.wardcheck_flag = #{wardcheckFlag}</if>
        <if test="inDeptcheckFlag != null ">and b.in_deptcheck_flag = #{inDeptcheckFlag}</if>
        <if test="inWardcheckFlag != null ">and b.in_wardcheck_flag = #{inWardcheckFlag}</if>
        <if test="diagcheckFlag != null ">and b.diagcheck_flag = #{diagcheckFlag}</if>
        <if test="encounterSourceId != null ">and b.encounter_source_id = #{encounterSourceId}</if>
        <if test="importanceFlagCode != null ">and b.importance_flag_code = #{importanceFlagCode}</if>
        <if test="emergencyLevelCode != null ">and b.emergency_level_code = #{emergencyLevelCode}</if>
        <if test="cry != null and cry == 0 ">and b.endtime is null</if>
        <if test="cry != null and cry == 1 ">and b.inhospstate=1</if>
        <if test="cry != null and cry == 2 ">and b.inhospstate=2</if>
        <if test="cry != null and cry == 3 ">and b.inhospstate=3</if>
        <if test="inhospstate != null ">and b.inhospstate = #{inhospstate}</if>
        <if test="schemestatus != null ">and b.schemestatus = #{schemestatus}</if>
        <if test="outWayId != null ">and b.out_way_id = #{outWayId}</if>
        <if test="outWayName != null ">and b.out_way_name = #{outWayName}</if>
        <if test="leaveldeptcode != null ">and b.leaveldeptcode = #{leaveldeptcode}</if>
        <if test="leavediagname != null  and leavediagname != ''">and b.leavediagname like concat('%',
            #{leavediagname}, '%')
        </if>
        <if test="drname != null  and drname != ''">and b.drname like concat('%', #{drname}, '%')</if>
        <if test="leaveldeptname != null  and leaveldeptname != ''">and b.leaveldeptname like concat('%',
            #{leaveldeptname}, '%')
        </if>
        <if test="deptname != null  and deptname != ''">and b.deptname like concat('%',
            #{deptname}, '%')
        </if>
        <if test="patid != null  and patid != ''">and a.id =#{patid}
        </if>
        <if test="leavehospitaldistrictname != null  and leavehospitaldistrictname != ''">and
            b.leavehospitaldistrictname like concat('%', #{leavehospitaldistrictname}, '%')
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size()>0">
            AND b.leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                     close=")">
                #{leavehospitaldistrictcode}
            </foreach>
        </if>
        <if test="hospitaldistrictcodeList != null and hospitaldistrictcodeList.size()>0">
            AND b.hospitaldistrictcode IN
            <foreach collection="hospitaldistrictcodeList" item="hospitaldistrictcode" open="(" separator=","
                     close=")">
                #{hospitaldistrictcode}
            </foreach>
        </if>
        <if test="leaveldeptcodes != null and leaveldeptcodes.size()>0">
            AND b.leaveldeptcode IN
            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                     close=")">
                #{leaveldeptcode}
            </foreach>
        </if>
        <if test="deptcodeList != null and deptcodeList.size()>0">
            AND b.deptcode IN
            <foreach collection="deptcodeList" item="deptcode" open="(" separator=","
                     close=")">
                #{deptcode}
            </foreach>
        </if>
        <if test="icd10codeList != null and icd10codeList.size()>0">
            AND b.leaveicd10code IN
            <foreach collection="icd10codeList" item="icd10code" open="(" separator=","
                     close=")">
                #{icd10code}
            </foreach>
        </if>
        <if test="medicalCode != null and medicalCode != ''">and b.medical_code = #{medicalCode}</if>
        <if test="medicalName != null and medicalName != ''">and b.medical_name = #{medicalName}</if>
        <if test="medicalCompany != null and medicalCompany != ''">and b.medical_company = #{medicalCompany}</if>
        <include refid="selectPatMedInhospListFromWhere"/>
        GROUP BY
        b.inhospid,
        a.age,
@@ -403,6 +432,28 @@
                </otherwise>
            </choose>
        </if>
    </select>
    <!--
      分页总数(PageHelper 手写 count,id = 主查询 id + _COUNT 会被自动采用)。
      原状态:主查询带 GROUP BY,pagehelper 的 CountSqlParser#isSimpleCount 判定为
      "不能简化",于是总数变成 SELECT count(0) FROM ( 上面那条 60 列查询 ) tmp_count —
      等于每次翻页把整条查询再跑一遍。
      这里保持【完全相同的 FROM/WHERE/GROUP BY】(共用 selectPatMedInhospListFromWhere 片段,
      条件不会漂),但子查询只 select 1,不物化 60 列,也不带 order by。
      因为分组键包含 a.id 而这个 join 是一对一,分组数 == join 结果行数,总数与原来一致。
    -->
    <select id="selectPatMedInhospList_COUNT" parameterType="com.ruoyi.inhospvisit.domain.PatMedInhosp"
            resultType="java.lang.Long">
        select count(1)
        from (
            select 1
            FROM
            <include refid="selectPatMedInhospListFromWhere"/>
            group by b.inhospid, a.age, a.age_unit, a.telcode, a.id, a.sex
        ) t
    </select>
    <select id="selectPatMedInhospListBySerialnum" parameterType="com.ruoyi.inhospvisit.domain.PatMedInhosp"
@@ -503,6 +554,31 @@
        order by b.inhospid desc
    </select>
    <!--
      在院信息刷新的取数:只查 pat_med_inhosp 自身、只取刷新要用的列。
      刻意不复用 selectPatMedInhospList —— 那个查询 join 了 pat_archive 且要求
      a.idcardno IS NOT NULL,会让"证件号还没补上的新入院患者"静默漏刷新。
      WHERE (del_flag, orgid, inhospstate) 命中 idx_inhosp_optimize 的前缀。
    -->
    <select id="selectInhospRefreshCandidates" resultMap="PatMedInhospResult">
        select inhospid,
               serialnum,
               patname,
               orgid,
               campusid,
               deptcode,
               deptname,
               hospitaldistrictcode,
               hospitaldistrictname,
               hospitaldistrictid,
               bed_no
        from pat_med_inhosp
        where inhospstate = '0'
          and del_flag = '0'
          and orgid = #{orgid}
        order by inhospid asc
    </select>
    <select id="selectPatMedInhospListByCondition" parameterType="com.ruoyi.inhospvisit.domain.PatMedInhospVO"
            resultMap="PatMedInhospResult">
        select CONCAT( a.age, a.age_unit ) AS age,