MySQL - 过程,游标,内部联接

时间:2018-02-04 18:11:43

标签: mysql stored-procedures sql-update cursor inner-join

所以,我有一张更新患者的表格。状态根据他们最新提交的信息。在每天结束时,我检查患者当天是否完成了治疗,根据这些结果,我填写一张表格,然后向患者发送电子邮件(如果他们正在接受治疗),或他们的照顾者(如果他们不是)。

在我们为看护人提供电子邮件之前,我使用的是计算参与度的每日存储过程,以及用于汇总相关消息的连接查询。它看起来像这样:

 DELIMITER $$ 
CREATE DEFINER=CURRENT_USER PROCEDURE `proc_day_calc`()
    NO SQL
    COMMENT 'calculates days and fills table with messages (tbl_to_mail)'
BEGIN

    UPDATE `tbl_patient_status` SET d0 = d0 + 1, updated_by = 'd0count', checked = 1;

    UPDATE `tbl_patient_status` SET 
        d1 = d1 + 1, 
        d4 = d4 + 1, 
        patient_status = 'seguimiento',
        updated_by = 'proc_day_calc.seg', 
        checked = 2 
    WHERE checked = 1 AND latest_submit >= NOW() - INTERVAL 1 DAY;

    UPDATE `tbl_patient_status` SET 
        d2 = d2 + 1,
        d4 = 0,
        patient_status = 'contingencia', 
        updated_by = 'proc_day_calc.cont',
        checked = 2
    WHERE checked = 1 AND latest_submit < NOW() - INTERVAL 1 DAY;

    UPDATE `tbl_patient_status` SET 
        d3 = d3 + 1,
        patient_status = 'post',
        updated_by = 'd0count',
        checked = 2
    WHERE d1 >= 22 AND patient_status = 'cierre';

    UPDATE `tbl_patient_status` SET 
        patient_status = 'drop-out',
        updated_by = 'proc_day_calc'
    WHERE latest_submit < NOW() - INTERVAL 10 DAY AND checked = 1 AND patient_status = 'contingencia';

    INSERT INTO tbl_to_mail (to_email, subject, body)
        SELECT DISTINCT id_user, subject, body FROM tbl_patient_status INNER JOIN lst_msg_treatmnt USING (`patient_status`, `language`, `role`) WHERE tbl_patient_status.checked = 2 AND tbl_patient_status.d1 = lst_msg_treatmnt.on_d1 OR tbl_patient_status.d2 = lst_msg_treatmnt.on_d2 OR tbl_patient_status.d3 = lst_msg_treatmnt.on_d3 OR tbl_patient_status.d4 = lst_msg_treatmnt.on_d4;
    UPDATE `tbl_patient_status` SET checked = 3;

END$$
DELIMITER ;

**我正在努力修复将所有行更新为3的故障,而不仅仅是那些获取消息的人,但这并不是什么大问题,因为患者设置的每个新输入都检查= 0,然后那天(d0)将它设置回1,所以检查基本上是一个衡量我知道过程是否顺利进行的指标。

现在,我们需要添加护理人员,并将他们的电子邮件CONCAT放入一个字段(以减少发送的电子邮件数量),我尝试通过逐行计算引入光标以使程序更精确(我稍后会必须为每一行添加更多计算),但光标在第一个UPDATE(d0count)后停止。但是,如果我删除了那个UPDATE查询,那么它只完成第一个IF语句或CASE(两个都尝试过),然后在没有进入其他情况下的行的情况下关闭:

DROP PROCEDURE `proc_day_calc`;
CREATE DEFINER=CURRENT_patient PROCEDURE `proc_day_calc`() NOT DETERMINISTIC NO SQL SQL SECURITY DEFINER BEGIN

    DECLARE checked INT;
    DECLARE latest_submit DATETIME;
    DECLARE patient_status TEXT;
    DECLARE row_not_found TINYINT DEFAULT FALSE;

    DECLARE cursor_patientstatus CURSOR FOR SELECT checked, latest_submit, patient_status FROM `tbl_patient_status` WHERE checked = 1;

    DECLARE CONTINUE HANDLER FOR NOT FOUND 
        SET row_not_found = TRUE;

    UPDATE tbl_patient_status SET d0 = d0 + 1, updated_by = 'd0count', checked = 1;

    OPEN cursor_patientstatus;

    WHILE row_not_found = FALSE DO 

        FETCH cursor_patientstatus INTO checked, latest_submit, patient_status;

        IF checked = 1 AND latest_submit >= NOW() - INTERVAL 1 DAY THEN

            UPDATE `tbl_patient_status` SET 
                d1 = d1 + 1, 
                d4 = d4 + 1, 
                patient_status = 'seguimiento',
                updated_by = 'proc_day_calc.seg', 
                checked = 2;

            ### INSERTS MESSAGES TO SEND ONLY FOR patientS (NO MESSAGES FOR CAREGIVERS ON SEGUIMIENTO)
            INSERT INTO tbl_to_mail (role, id_patient, username, to_mail, subject, body, added_by)
                SELECT DISTINCT lst_msg_treatmnt.role, tbl_profile_patient.id_patient, tbl_profile_patient.username, tbl_profile_patient.email, lst_msg_treatmnt.subject, lst_msg_treatmnt.body, 'proc_day_calc.seg'
                FROM tbl_patient_status
                INNER JOIN lst_msg_treatmnt
                INNER JOIN tbl_profile_patient
                ON tbl_patient_status.id_patient = tbl_profile_patient.id_patient AND tbl_profile_patient.language = lst_msg_treatmnt.language AND tbl_patient_status.d1 = lst_msg_treatmnt.on_d1 OR tbl_patient_status.d4 = lst_msg_treatmnt.on_d4
            WHERE lst_msg_treatmnt.role = 'patient' AND lst_msg_treatmnt.patient_status = 'seguimiento' AND tbl_patient_status.checked = 2;

            UPDATE `tbl_patient_status` SET checked = 3;

        ELSEIF checked = 1 AND latest_submit < NOW() - INTERVAL 1 DAY THEN
            UPDATE `tbl_patient_status` SET 
                    d2 = d2 + 1,
                    d4 = 0,
                    patient_status = 'contingencia', 
                    updated_by = 'proc_day_calc.cont',
                    checked = 2;

            ### INSERTS MESSAGES TO SEND - ONE INNER JOIN PER TABLE (patient)
            INSERT INTO tbl_to_mail (role, id_patient, username, to_mail, subject, body, added_by)
                SELECT DISTINCT 'patient', tbl_profile_patient.id_patient, tbl_profile_patient.username, tbl_profile_patient.email, lst_msg_treatmnt.subject, lst_msg_treatmnt.body, 'proc_day_calc.cont'
                FROM tbl_patient_status
                INNER JOIN lst_msg_treatmnt
                INNER JOIN tbl_profile_patient
                ON tbl_patient_status.id_patient = tbl_profile_patient.id_patient AND tbl_profile_patient.language = lst_msg_treatmnt.language AND tbl_patient_status.d2 = lst_msg_treatmnt.on_d2
            WHERE lst_msg_treatmnt.role = 'patient' AND lst_msg_treatmnt.patient_status = 'contingencia' AND tbl_patient_status.checked = 2;


            ### INSERTS MESSAGES TO SEND - ONE INNER JOIN PER TABLE (CAREGIVERS)
            INSERT INTO tbl_to_mail (role, id_patient, username, to_mail, subject, body, added_by)
                SELECT DISTINCT lst_msg_treatmnt.role, tbl_profile_caregiver.id_patient, NULL,  GROUP_CONCAT(tbl_profile_caregiver.email), lst_msg_treatmnt.subject, lst_msg_treatmnt.body, 'proc_day_calc.cont'
                FROM tbl_patient_status
                INNER JOIN lst_msg_treatmnt
                INNER JOIN tbl_profile_caregiver
                ON tbl_patient_status.id_patient = tbl_profile_caregiver.id_patient AND tbl_profile_caregiver.language = lst_msg_treatmnt.language AND tbl_patient_status.d2 = lst_msg_treatmnt.on_d2
                WHERE lst_msg_treatmnt.patient_status = 'contingencia' AND lst_msg_treatmnt.role = 'caregiver' AND  tbl_patient_status.checked = 2;

            UPDATE `tbl_patient_status` SET checked = 3;

        ### CIERRE doesn't send messages because TF_Day_21 activates Apiant on its own, but it doesn't send messages for CAREGIVERS!!! COME FIX 
        ELSEIF checked = 1 AND patient_status = 'cierre' THEN
            UPDATE `tbl_patient_status` SET 
                    d3 = d3 + 1,
                    patient_status = 'post',
                    updated_by = 'proc_day_calc.post',
                    checked = 2;

        ELSEIF latest_submit < NOW() - INTERVAL 10 DAY AND checked = 1 AND patient_status = 'contingencia' THEN
            UPDATE `tbl_patient_status` SET 
                patient_status = 'drop-out',
                updated_by = 'proc_day_calc.drop',
                checked = 2;
        END IF;
    END WHILE;

    CLOSE cursor_patientstatus;


END

任何和所有帮助将不胜感激!与此同时,我通过运行两个单独的程序来修补它。第一个计算天数,第二个计算消息。我可以在一个过程中完成所有操作吗?或者,运行这些计算的最有效和最精确的方法是什么。

谢谢!

0 个答案:

没有答案