如何使用MySQL填充一个表(A)的另一表(B)的缺失行?

时间:2018-09-04 13:45:03

标签: mysql sql

我正在用PHP和MySQL建立一个虚拟教室。该教室由课程组成,每个课程包含不同的主题或模块。学生必须检查每个模块,最后,通过摘要(评估板)来了解学生是否通过了课程。

话虽如此,我有一个表,用于存储每个学生的评估,并在其中保存 inscripcion_id (学生-题词ID), modulo_id (模块ID) , fecha (考试日期), aciertos (number_of_right_answers), ultima_convocatoria (评估_last_convocatory)和estado(状态)。

SQL小提琴-> here

通过一些先前建立的规则,告诉我学生是否通过了某个模块,我得到了以下数据集:

+----------------+-----------+---------------------+----------+---------------------+--------+------------+
| inscripcion_id | modulo_id |        fecha        | aciertos | ultima_convocatoria | estado |     ev     |
+----------------+-----------+---------------------+----------+---------------------+--------+------------+
|            890 |         1 | 2018-01-24 22:26:09 |        8 |                   2 |      1 | aprobado   |
|            890 |         2 | 2018-01-24 22:36:58 |        3 |                   3 |      0 | suspendido |
|            890 |         5 | 2018-01-24 22:38:50 |        3 |                   1 |      0 | suspendido |
|            890 |         6 | 2018-01-24 22:44:20 |        7 |                   3 |      0 | suspendido |
|            891 |         1 | 2018-01-25 09:24:42 |        8 |                   1 |      1 | aprobado   |
|            891 |         2 | 2018-01-25 10:01:55 |        4 |                   8 |      0 | suspendido |
|            891 |         4 | 2018-01-25 10:51:49 |        5 |                   3 |      1 | suspendido |
|            891 |         5 | 2018-01-25 10:23:45 |        9 |                   1 |      1 | aprobado   |
|            891 |         6 | 2018-01-25 11:21:20 |        7 |                   3 |      0 | suspendido |
|            896 |         1 | 2018-01-25 11:55:48 |        1 |                   1 |      1 | suspendido |
|            898 |         1 | 2018-01-25 14:01:51 |        6 |                   1 |      1 | suspendido |
|            907 |         1 | 2018-03-25 16:06:18 |        3 |                   1 |      0 | suspendido |
|            907 |         2 | 2018-03-25 16:07:34 |        3 |                   1 |      0 | suspendido |
|            907 |         3 | 2018-03-25 16:09:04 |        3 |                   1 |      0 | suspendido |
|            907 |         4 | 2018-03-25 16:08:13 |        3 |                   1 |      0 | suspendido |
|            907 |         5 | 2018-03-25 16:10:37 |        2 |                   1 |      0 | suspendido |
|            907 |         6 | 2018-03-25 16:08:44 |        3 |                   1 |      0 | suspendido |
+----------------+-----------+---------------------+----------+---------------------+--------+------------+

此数据是通过以下查询获得的:

SELECT  e1.inscripcion_id,
        e1.modulo_id,
        e1.fecha,
        e1.aciertos,
        e1.convocatoria AS ultima_convocatoria,
        e1.estado,
        if  (
                ( e1.modulo_id in (SELECT modulo.modulo_id FROM modulo WHERE modulo.curso_id = 1 AND modulo.categoria_id = 1)
                    AND e1.aciertos <= 7 )
                OR ( e1.modulo_id = (SELECT modulo.modulo_id FROM modulo WHERE modulo.curso_id = 1 AND modulo.categoria_id = 2)
                    AND e1.aciertos <= 11 ),
                "suspendido",
                "aprobado"
        ) AS ev
FROM    (
            SELECT  inscripcion_id,
                    modulo_id,
                    MAX(convocatoria) AS max_convocatoria
            FROM `evaluacion`
            GROUP BY    inscripcion_id,
                        modulo_id
            ORDER BY    `inscripcion_id` ASC,
                        `modulo_id` ASC,
                        `convocatoria` ASC
) AS e2
INNER JOIN evaluacion AS e1
    ON e1.inscripcion_id = e2.inscripcion_id
    AND e1.modulo_id = e2.modulo_id
    AND e1.convocatoria = e2.max_convocatoria

如您所见,学生890已经制作了模块1、2、5和6。我要实现的是,这些模块仍在等待处理中,因此我也得到了以前的数据组。例子:

+----------------+-----------+---------------------+----------+---------------------+--------+------------+
| inscripcion_id | modulo_id |        fecha        | aciertos | ultima_convocatoria | estado |     ev     |
+----------------+-----------+---------------------+----------+---------------------+--------+------------+
|            890 |         1 | 2018-01-24 22:26:09 | 8        | 2                   | 1      | aprobado   |
|            890 |         2 | 2018-01-24 22:36:58 | 3        | 3                   | 0      | suspendido |
|            890 |         3 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            890 |         4 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            890 |         5 | 2018-01-24 22:38:50 | 3        | 1                   | 0      | suspendido |
|            890 |         6 | 2018-01-24 22:44:20 | 7        | 3                   | 0      | suspendido |
|            891 |         1 | 2018-01-25 09:24:42 | 8        | 1                   | 1      | aprobado   |
|            891 |         2 | 2018-01-25 10:01:55 | 4        | 8                   | 0      | suspendido |
|            891 |         3 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            891 |         4 | 2018-01-25 10:51:49 | 5        | 3                   | 1      | suspendido |
|            891 |         5 | 2018-01-25 10:23:45 | 9        | 1                   | 1      | aprobado   |
|            891 |         6 | 2018-01-25 11:21:20 | 7        | 3                   | 0      | suspendido |
|            896 |         1 | 2018-01-25 11:55:48 | 1        | 1                   | 1      | suspendido |
|            896 |         2 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            896 |         3 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            896 |         4 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            896 |         5 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            896 |         6 | NULL                | NULL     | NULL                | NULL   | pendiente  |
|            ... |           |                     |          |                     |        |            |
+----------------+-----------+---------------------+----------+---------------------+--------+------------+

结果是添加了学生尚未完成的模块,并为 ev 列添加了新值“ pending”。

我不知道该怎么做...我尝试过,我搜索了互联网,但什么都没有:(

最终目标是什么?我要获得的所有学生都拥有待修课程(即他们有 some 个待修模块)的最终名单。 / s),向他们发送提醒电子邮件,通知他们必须检查剩余模块的自身。对于已批准或暂停的人,不会向他们发送电子邮件。

你能帮我吗?

SQL小提琴-> here

非常感谢

2 个答案:

答案 0 :(得分:1)

假设您希望让评估表中没有模块的学生像示例中提供的那样“待定”。让学生加入所有模块的方法是对moduloevaluacion进行完全加入,以获得完整的inscripcion_id modulo_id的完整集合。然后与现有查询左联接将提供您想要的结果。

sqlfiddle

SELECT fs.inscripcion_id, 
       fs.modulo_id, 
       e3.fecha, 
       e3.aciertos, 
       e3.ultima_convocatoria, 
       e3.estado, 
       IF(e3.ev IS NULL, "pendiente", e3.ev) AS ev 
FROM   (SELECT m.modulo_id, 
               e.inscripcion_id 
        FROM   modulo m, 
               evaluacion e 
        GROUP  BY m.modulo_id, 
                  e.inscripcion_id) AS fs 
       LEFT JOIN (SELECT 
                                          e1.inscripcion_id, 
                         e1.modulo_id, 
                         e1.fecha, 
                         e1.aciertos, 
                         e1.convocatoria 
                                                            AS 
                                          ultima_convocatoria 
                                          , 
                         e1.estado, 
                         IF (( e1.modulo_id IN (SELECT modulo.modulo_id 
                                                FROM   modulo 
                                                WHERE  modulo.curso_id = 1 
                                                       AND modulo.categoria_id = 
                                                           1) 
                               AND e1.aciertos <= 7 ) 
                              OR ( e1.modulo_id = (SELECT modulo.modulo_id 
                                                   FROM   modulo 
                                                   WHERE 
                                   modulo.curso_id = 1 
                                   AND modulo.categoria_id = 2) 
                                   AND e1.aciertos <= 11 ), "suspendido", 
                         "aprobado") 
                                          AS ev 
                  FROM   (SELECT inscripcion_id, 
                                 modulo_id, 
                                 Max(convocatoria) AS max_convocatoria 
                          FROM   `evaluacion` 
                          GROUP  BY inscripcion_id, 
                                    modulo_id 
                          ORDER  BY `inscripcion_id` ASC, 
                                    `modulo_id` ASC, 
                                    `convocatoria` ASC) AS e2 
                         INNER JOIN evaluacion AS e1 
                                 ON e1.inscripcion_id = e2.inscripcion_id 
                                    AND e1.modulo_id = e2.modulo_id 
                                    AND e1.convocatoria = e2.max_convocatoria) 
                 AS e3 
              ON fs.modulo_id = e3.modulo_id 
                 AND fs.inscripcion_id = e3.inscripcion_id 
ORDER  BY fs.inscripcion_id, 
          fs.modulo_id; 

对于进一步的问题, 您可能要使用

SELECT inscripcion_id,
    SUM(case when ev = 'aprobado' then 1 else 0 end) as approved_cnt,
    SUM(case when ev = 'suspendido' then 1 else 0 end) as suspended_cnt,
    SUM(case when ev = 'pendiente' then 1 else 0 end) as pending_cnt 
From --the above query...
Group by inscripcion_id

获取每个学生的状态计数,然后使用这些计数进行逻辑计算。

答案 1 :(得分:0)

查看新的sqlfiddle之后 我在下面编写了查询,我认为它应该可以满足您的需求

请注意,每个模块评估不只一次,这意味着每个模块将获得不止一种状态

要解决此问题,您可以添加一个group语句(现在在评论中) 或者您根据自己的需求进行了不同的评估...

SELECT
  i.inscripcion_id,
  c.curso_id,
  c.titulo AS curso_titulo,
  m.modulo_id,
  m.titulo AS modulo_titulo,
  IFNULL(ev.estado,0) AS estado,
  m.*
 FROM
   inscripcion i
   INNER JOIN curso c ON c.curso_id = i.curso_id
   INNER JOIN modulo m ON m.curso_id = c.curso_id
   LEFT JOIN evaluacion ev ON ev.modulo_id = m.modulo_id
 WHERE
   (ev.estado = 0 OR ev.estado IS NULL)
/*
GROUP BY
 m.modulo_id
*/

;