【问题标题】:How do I use conditions in one table and update record in another table如何在一个表中使用条件并在另一个表中更新记录
【发布时间】:2017-09-22 17:18:59
【问题描述】:
CREATE TABLE candidate_subjects (
  id INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT,
  candidate_id INT(11),
  exam_type_id INT(10),
  subject_id INT(10),
  ca_score INT(11),
  exam_score INT(6),
  score_grade VARCHAR(10),
  date_created VARCHAR(10),
  date_modified TIMESTAMP
);

INSERT INTO `candidate_subjects` (`id`, `candidate_id`, `exam_type_id`, 
`subject_id`, `ca_score`, `exam_score`, `score_grade`, `date_created`, 
`date_modified`) VALUES
  (1, 2, 1, 32, 22, 61, NULL, '2017-02-01', '2017-08-28 13:10:33'),
  (2, 2, 1, 5, 21, 38, NULL, '2017-02-01', '2017-08-28 13:10:33'),
  (3, 2, 1, 14, 21, 51, NULL, '2017-02-01', '2017-08-28 13:10:33'),
  (4, 2, 1, 1, 19, 34, NULL, '2017-02-01', '2017-08-28 13:10:33'),
  (5, 2, 1, 2, 23, 39, NULL, '2017-02-01', '2017-08-28 13:10:33'),
  (6, 2, 1, 38, 20, 32, NULL, '2017-02-01', '2017-08-28 13:10:33'),
  (7, 2, 1, 53, 24, 47, NULL, '2017-02-01', '2017-08-28 13:10:33'),
  (8, 4, 1, 32, 19, 61, NULL, '2017-02-01', '2017-08-28 13:11:27'),
  (9, 4, 1, 5, 22, 41, NULL, '2017-02-01', '2017-08-28 13:11:27'),
  (10, 4, 1, 14, 20, 46, NULL, '2017-02-01', '2017-08-28 13:11:27'),
  (11, 4, 1, 1, 23, 37, NULL, '2017-02-01', '2017-08-28 13:11:27'),
  (12, 4, 1, 2, 21, 36, NULL, '2017-02-01', '2017-08-28 13:11:27'),
  (13, 4, 1, 38, 22, 34, NULL, '2017-02-01', '2017-08-28 13:11:27'),
  (14, 4, 1, 53, 24, 52, NULL, '2017-02-01', '2017-08-28 13:11:27'),
  (15, 5, 1, 32, 20, 62, NULL, '2017-02-01', '2017-08-28 13:11:44'),
  (16, 5, 1, 5, 22, 38, NULL, '2017-02-01', '2017-08-28 13:11:44');


CREATE TABLE candidates (
  id INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
  exam_no VARCHAR(15),
  surname VARCHAR(50),
  other_names VARCHAR(100),
  school_id INT(11),
  registration_completed INT(11),
  exam_scores_completed INT(5),
  remark VARCHAR(10)
);

INSERT INTO candidates (id, exam_no, surname, other_names, school_id,
registration_completed, exam_scores_completed, remark) VALUES
 (1, '1171052001', 'ABADO', 'MASENENGEN', 1052, 1, '1', ''),
 (2, '1170938001', 'AGBA', 'NGUHER', 938, 1, '1', ''), 
 (3, '1170071001', 'ABEE', 'SESUUR', 71, 1, '1', ''),
 (4, '1170938002', 'AHEN', 'REBECCA DOOSUUN', 938, 1, '1', '');

在上面,我有一个表 Candidate 和另一个表 Candidate_subjects,分别用于存储候选人详细信息和候选人分数。 Candidate_subjects 有考生的科目分数。注意数学的科目 ID 是 2,英语 ID 是 1。及格分数是 40,即 ca_score + Exam_score 的总和。候选人备注的条件是(数学 = 40 and eng >= 40) and total subjects pass >=6 remark is 'PASS' else if (math 40 and eng > 40) and total subjects pass

下面是我写的查询,但它没有给出预期的结果:

UPDATE candidates SET candidates.remark='FAIL' WHERE (select 
    count(candidate_subjects.id) AS total_pass from candidates, 
    candidate_subjects where candidates.id=candidate_subjects.candidate_id 
    and (candidate_subjects.ca_score + candidate_subjects.exam_score) >= 40) < 6

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    要根据您的条件更新候选人备注列,它可能是一个复杂的查询

    update candidates c
    join (
    
        select a.candidate_id,a.total_pass,
        e.ca_score + e.exam_score as english,
        m.ca_score + m.exam_score as maths
        from (select 
            count(id) AS total_pass ,candidate_id
            from candidate_subjects 
            where(ca_score + exam_score) >= 40
            group by candidate_id
        ) a
        left join candidate_subjects e on (a.candidate_id = e.candidate_id
                                           and e.subject_id = 1) /* english id */
        left join candidate_subjects m on (a.candidate_id = m.candidate_id
                                           and m.subject_id = 2) /* maths id */
    
    ) t on c.id = t.candidate_id
    set c.remark = case 
        when t.maths < 40 or t.english < 40 then 'RESIT'
        when t.maths >= 40 and t.english >= 40 and t.total_pass >= 6 then 'PASS'
        when t.maths < 40 and t.english < 40 and t.total_pass < 6 then 'FAIL' 
        when t.maths > 40 and t.english > 40 and t.total_pass < 6 then 'FAIL'
        else c.remark
    end;
    

    DEMO

    SELECT *

    SELECT ids

    一些注意事项可确保您的架构中有以下索引

    • candidate_id in Candidate_subjects 应设置为对候选表的外键引用并应被索引

    • 在 (ca_score + Exam_score) 上添加复合索引

    • 为 subject_id 添加索引

    如果您仍然面临长时间执行问题,请像join(....) 部分添加那样批量运行中断查询

    order by a.candidate_id asc
    limit start,end // set these like 0,10000, 10000,10000, 20000,10000 .....
    

    LIMIT

    【讨论】:

    • @M Khalid Junaid 感谢您的更新。当我在我的数据库上运行查询时,我看到了以下错误。无法识别的关键字。 (在位置 598 的“case”附近)无法识别的关键字。 (在位置 609 的“何时”附近)意外标记。 (在位置 614 的“t”附近)意外标记。 (在位置 615 的“.”附近)意外的标记。 (靠近位置 616 的“数学”)意外标记。 (在位置 622 的“
    • 我对查看上述错误感到困惑,您是如何使用/操作此查询的?如在 sql fiddle demo 中,您可以看到 RDBMS 设置为 Mysql 并且在那里运行良好,对于上述错误我不知道除非您提供一些详细信息
    • @M Khalid Junaid 我后来发现这是我更正的列名的问题,并且查询处理了很长时间并停止。也许是因为表格有很多数据。候选人表有 70,500 条记录,candidate_subjects 有 500,488 条记录。你觉得我应该怎么做?
    • @M Khalid Junaid 我有 70,626 个候选人,他们的 id 从 1 到 70626 开始。我有 500,488 条 Candidate_subjects 表记录。 Mysql 处理查询很长时间并停止。您不认为我应该像 10,000 名候选人那样分批运行查询。如果是这样,我该如何运行查询,例如 1 到 10,000,然后 10,001 到 20,000 等等。谢谢
    • @Moses 我已经更新了我的答案看看,是的,你可以通过应用限制来查询
    【解决方案2】:

    在哪里?当您对 WHERE 条件使用子选择时,请将其视为 IN() 子句。返回的值需要是条件逻辑中使用的值,在本例中为 FK/ID。

    您查询的最后一部分对我来说也没有意义。这有意义吗?

    UPDATE candidates SET candidates.remark = 'FAIL' 
    WHERE candidates.id IN 
        (SELECT candidate_id FROM
            (SELECT candidate_id, count(candidate_subjects.id) AS total_pass
            FROM candidates, candidate_subjects
            WHERE candidates.id = candidate_subjects.candidate_id
            AND (candidate_subjects.ca_score + candidate_subjects.exam_score) >= 40)
        GROUP BY candidate_id
        HAVING total_pass = 6);
    

    认为有一些语法错误,但希望它有所帮助。这些子选择可能需要别名...(...) AS sub1,。想不起来了。

    我会反过来处理这个问题,制作一个返回您想要更新的正确candidate.id 值的查询。然后在该 SQL 测试并正常运行后,将其添加到您的更新中:

    UPDATE candidates SET candidates.remark = 'FAIL' 
    WHERE candidates.id IN (**THE SQL YOU WROTE AND TESTED RETURNING THE CORRECT IDS**)
    

    【讨论】:

      【解决方案3】:

      使用简单的子查询。

      UPDATE candidates
      SET candidates.remark='FAIL'
      WHERE (
            SELECT count(*) from candidate_subjects 
            WHERE candidate_id=candidates.id and (candidate_subjects.ca_score + candidate_subjects.exam_score) >= 40)
      ) < 6
      

      【讨论】:

        猜你喜欢
        • 2013-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多