通过检查MySQL中其他三个表的信息来更新一个表的记录


UPDATE records of a table by checking the information from other three tables in MySQL

我有以下表格:

wi_individiual_g(ind_id, ind_name, ...)
wi_training(trn_id, trn_name, ...)
wi_group(grp_id, grp_name, ...)

在这里,一个群体可以由以下个人组成:

wi_indv_org(ind_id, grp_id, is_deleted)

培训可以提供给一个团体或个人。也就是说,训练可以由多个组和其他单独的个人组成(也可以来自不属于训练的其他组)。为此,我创建了两个表:

wi_trn_org(trn_id, grp_id, is_deleted)
wi_indv_training(ind_id,trn_id,is_deleted)

在wi_indv_training中,个人来自正在训练的组或来自如上所述的匿名组。在输入超过200K的数据后,我在wi_indv_training中添加了一列indv_source。作为

wi_indv_training(ind_id,trn_id,indv_source, is_deleted)

此列检查个人是来自组还是匿名组。如果个人来自组,则标记为group,否则标记为individual。这个概念适用于新输入的数据。但我需要更新之前的数据20万,以检查参与培训的个人是团体来源还是个人来源。为了解决这个问题,我编写了这段PHP代码,但执行起来需要超过15分钟。

$trn=$this->db->pdoQuery("SELECT DISTINCT(trn_id) AS trn_id FROM wi_indv_training WHERE is_deleted=0")->results();
        foreach ($trn as $key => $value) {
            $trn_id=$value['trn_id'];
            $grp=$this->db->pdoQuery("UPDATE wi_indv_training SET indv_source='Group' 
                WHERE EXISTS
                (
                    SELECT DISTINCT(wi_indv_org.ind_id) FROM wi_indv_org 
                    INNER JOIN wi_trn_org ON wi_indv_org.grp_id=wi_trn_org.grp_id AND wi_trn_org.is_deleted=0 
                    AND wi_trn_org.is_deleted=0
                    AND wi_trn_org.trn_id=$trn_id
                ) 
                AND ind_id IN (
                    SELECT DISTINCT(wi_indv_org.ind_id) FROM wi_indv_org 
                    INNER JOIN wi_trn_org ON wi_indv_org.grp_id=wi_trn_org.grp_id AND wi_trn_org.is_deleted=0 
                    AND wi_trn_org.is_deleted=0
                    AND wi_trn_org.trn_id=$trn_id
                );UPDATE wi_indv_training SET indv_source='Individual' WHERE trn_id=$trn_id AND ind_id NOT IN (
                    SELECT DISTINCT(wi_indv_org.ind_id) FROM wi_indv_org 
                    INNER JOIN wi_trn_org ON wi_indv_org.grp_id=wi_trn_org.grp_id AND wi_trn_org.is_deleted=0 
                    AND wi_trn_org.is_deleted=0
                    AND wi_trn_org.trn_id=$trn_id
                )");
        }

SQL中的要求是:;

Step 1) To select a training. 
Step 2) Search for groups that are involved in training. 
Step 3) Search for individuals that are in groups provided by above step
Step 4) Update the table wi_indv_training records as indv_source='Group' if records found for that training
Step 5) Update all remaining records as indv_source='Individual' for provided training.

我需要一个执行速度快的解决方案。如果有人帮助我,我会很高兴的。谢谢!

尝试这两个查询,而不是for循环:

UPDATE wi_indv_training
    INNER JOIN wi_indv_org ON
        wi_indv_training.is_deleted=0
        AND wi_indv_org.trn_id=wi_indv_training.trn_id
    INNER JOIN wi_trn_org ON
        wi_indv_org.grp_id=wi_trn_org.grp_id
        AND wi_trn_org.is_deleted=0
        AND wi_trn_org.trn_id=wi_indv_training.trn_id
    SET
        wi_indv_training.indv_source = 'Group';
UPDATE wi_indv_training
    SET
        wi_indv_training.indv_source='Individual'
    WHERE
        AND wi_indv_training.is_deleted=0
        NOT EXISTS (
            SELECT ind_id
            FROM wi_indv_org
            WHERE
                wi_indv_org.trn_id = wi_indv_training.trn_id
                AND wi_indv_org.ind_id=wi_indv_training.ind_id
            LIMIT 1
        );

尽可能避免子查询,因为这会减慢查询速度。如果无法避免,至少可以通过限制子查询返回的行数来加快子查询的速度。

您的代码基本上运行:

SELECT COUNT (DISTINCT trn_id) FROM wi_indv_training

查询!如果wi_indv_training表中有200k行,则意味着您正在运行200k个查询,这就解释了为什么它如此缓慢。