mysql-为没有值的记录插入0

时间:2016-12-20 18:22:25

标签: mysql left-join

我正在构建一个应用程序,该应用程序将列出学生的考试相关详细信息。

CREATE TABLE IF NOT EXISTS `es_student` (
  `student_id` int(11) NOT NULL,
  `fname` varchar(50) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=latin1;

INSERT INTO `es_student` (`student_id`, `fname`) VALUES
(1,'John');

有多个科目

CREATE TABLE IF NOT EXISTS `es_subject` (
  `subject_id` int(11) NOT NULL,
  `subject` varchar(50) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=latin1;

INSERT INTO `es_subject` (`subject_id`, `subject`) VALUES
(1,'Math'),
(2,'English'),
(3,'Science'),
(4,'Physics');

有多个考试。但并非所有考试都是针对某一主题进行的。 例如:对于数学,所有三门考试都已进行,但对于英语,只进行了一次考试。因此,我希望将零作为未完成的考试(对于某个科目)的分数。

CREATE TABLE IF NOT EXISTS `es_exam` (
  `exam_id` int(11) NOT NULL,
  `exam` varchar(50) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=latin1;

INSERT INTO `es_exam` (`exam_id`, `exam`) VALUES
(1,'Exam 1'),
(2,'Exam 2'),
(3,'Exam 3');

这是我存储所有标记的方式

CREATE TABLE IF NOT EXISTS `es_mark` (
  `mark_id` int(11) NOT NULL,
  `exam_id` int(11) NOT NULL,
  `subject_id` int(11) NOT NULL,
  `student_id` int(11) NOT NULL,
  `mark` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=latin1;

INSERT INTO `es_mark` (`mark_id`, `exam_id`,`subject_id`, `student_id`,`mark`) VALUES
(1,1,1,1,11),
(2,2,1,1,15),
(3,3,1,1,12),
(4,3,2,1,11),
(5,1,3,1,1),
(6,3,3,1,2),
(7,2,4,1,3);

但是我写的查询对那些尚未进行的考试没有显示为零。

SELECT es_mark.mark_id,es_mark.mark,es_exam.exam ,es_subject.subject,es_subject.subject_id,es_student.fname
FROM es_mark
LEFT JOIN es_subject ON es_mark.subject_id=es_subject.subject_id
LEFT JOIN es_student ON es_mark.student_id=es_student.student_id
LEFT JOIN es_exam ON es_exam.exam_id=es_mark.exam_id
WHERE es_mark.student_id=1
GROUP BY es_mark.mark_id

这是我得到的结果:

mark_id     mark    exam    subject     subject_id  fname
1            11     Exam 1  Math           1        John
2            15     Exam 2  Math           1        John
3            12     Exam 3  Math           1        John
4            11     Exam 3  English        2        John
5            1      Exam 1  Science        3        John
6            2      Exam 3  Science        3        John
7            3      Exam 2  Physics        4        John

这就是我想要实现的目标:

mark_id     mark    exam    subject     subject_id  fname
1            11     Exam 1  Math         1          John
2            15     Exam 2  Math         1          John
3            12     Exam 3  Math         1          John
4            11     Exam 3  English      2          John
0             0     Exam 2  English      2          John
0             0     Exam 1  English      2          John

依旧......

是否有可能为那些尚未进行的考试插入零作为标记?

FIDDLE

P.S:mark_id无关紧要。我知道它不能重复,因为它是一个主键字段,我也把0放在所需的输出中。

4 个答案:

答案 0 :(得分:1)

你应该尝试这个查询,这个技巧是在带有两个交叉连接的deliverd表中。 这些交叉连接使用表es_subject,es_exam和es_student中的数据生成4 * 3 * 1 = 12条记录,以便在这三个表之间进行所有可能的组合。

请注意,你不能得到你试图达到的顺序,这就是为什么我的结果不同但是mark_id和mark是零,没有匹配。

SELECT 

   IF (es_mark.mark_id IS NULL, 0, es_mark.mark_id) AS mark_id
 , IF (es_mark.mark IS NULL, 0, es_mark.mark) AS mark
 , all_exam.exam
 , all_exam.subject
 , all_exam.subject_id
 , all_exam.fname 

FROM (
 SELECT 
   *
 FROM 
   es_subject
 CROSS JOIN
   es_exam
 CROSS JOIN 
   es_student 
) 
 AS
  all_exam 

LEFT JOIN
  es_mark
ON 
    all_exam.exam_id = es_mark.exam_id
  AND 
    all_exam.subject_id = es_mark.subject_id

LEFT JOIN 
  es_subject
ON
 es_mark.subject_id = es_subject.subject_id

 LEFT JOIN
  es_student    
 ON
  es_mark.student_id = es_student.student_id   

LEFT JOIN
  es_exam
ON
  es_exam.exam_id = es_mark.exam_id 

ORDER BY 
    all_exam.subject_id ASC
  , all_exam.exam ASC

结果

mark_id    mark  exam    subject  subject_id  fname   
-------  ------  ------  -------  ----------  --------
      1      11  Exam 1  Math              1  John    
      2      15  Exam 2  Math              1  John    
      3      12  Exam 3  Math              1  John    
      0       0  Exam 1  English           2  John    
      0       0  Exam 2  English           2  John    
      4      11  Exam 3  English           2  John    
      5       1  Exam 1  Science           3  John    
      0       0  Exam 2  Science           3  John    
      6       2  Exam 3  Science           3  John    
      0       0  Exam 1  Physics           4  John    
      7       3  Exam 2  Physics           4  John    
      0       0  Exam 3  Physics           4  John 

参见演示http://www.sqlfiddle.com/#!9/bfcae/6

答案 1 :(得分:0)

node.allKnobs()

答案 2 :(得分:0)

使用时必须使用DEFAULT值。 如果未指定其他值,则默认值将添加到所有新记录中。

答案 3 :(得分:0)

您需要将mark调整为以下内容:

`mark` int(11) DEFAULT 0 NOT NULL

根据您的示例显示,它正在将数据拉入mark字段并添加1,2&因此,由于提供了数据,所以它并没有默认为0。

对于INSERT查询,即使您声明具有DEFAULT值的列,它们也必须填充所有字段,因为它不会允许空数据字段。对于填充和未填充mark数据的查询,您需要具有单独的INSERT INTO查询。以下示例 -

INSERT INTO `es_mark` (`mark_id`, `exam_id`,`subject_id`, `student_id`,`mark`) VALUES
(1,1,1,1,11),
(2,2,1,1,15),
(3,3,1,1,12),
(4,3,2,1,11);
INSERT INTO `es_mark` (`mark_id`, `exam_id`,`subject_id`, `student_id`)
VALUES
(5,2,2,1),
(6,1,2,1);

希望这有助于您走上正确的道路,了解您希望通过项目实现的目标。