简体   繁体   中英

How do I use conditions in one table and update record in another table

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', '');

In above, I have a table candidates and another table candidate_subjects, for storing candidate details and candidate scores respectively. candidate_subjects have candidates score for subjects. Note subject ID for maths is 2, english Id is 1. Pass mark is 40, that is total of ca_score + exam_score. Condition for candidate remark is if total score for (math is < 40 or english is < 40) remark is 'RESIT'. else if (math >= 40 and eng >= 40) and total subjects passed >=6 remark is 'PASS' else if (score in math < 40 and score in eng < 40) and total subjects passed < 6 remark is 'FAIL' else if (math > 40 and eng > 40) and total subjects passed < 6 remark is FAIL.

Below is the query I have written but it is not giving the result expected:

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

WHERE what? When you use a subselect for a WHERE condition, think of it as an IN() clause. The value returned needs to be what is used in the conditional logic, the FK/ID in this case.

That last part of your query also didn't make sense to me. Does this make sense?

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);

Think there are some syntax errors though but hope it helps. Those subselects might need aliases... (...) AS sub1, . Can't recall.

I'd approach this in reverse, craft a query that returns the correct candidate.id values you want to update. Then with that SQL tested and working, add it to you update:

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

Use a simple subquery.

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

To update candidates remark column according to your criteria it can be a complex query as

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

Some considerations make sure you have following indexes in your schema

  • candidate_id in candidate_subjects should be set as a foreign key reference to candidates table and should be indexed

  • Add composite index on (ca_score + exam_score)

  • Add index for subject_id

If still you face long execution issue then run break your query in batches like in join(....) part add

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

LIMIT

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM