Mysql:连接三个基数为1:N的表

时间:2015-10-10 05:46:27

标签: mysql database

我有一个学院学校的数据库。它的结构有三个表: - 第一个是科目硕士。这个表可能有20多行。

CREATE TABLE `SUBJECTS` (
  `ID_SB` tinyint(4) NOT NULL AUTO_INCREMENT,
  `NAME` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID_SB`)
) 

- 第二个包含学生数据。这个可能有10000多行。

CREATE TABLE `STUDENTS` (
  `ID_ST` int(10) NOT NULL AUTO_INCREMENT,
  `NAME` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`ID_ST`)
) 

- 最后一个具有学生对每个科目的资格。它有大约1000行。

CREATE TABLE `QUALIFICATIONS` (
  `ID_CF` int(10) NOT NULL AUTO_INCREMENT,
  `ID_ST` int(10) DEFAULT NULL,
  `ID_SB` int(10) DEFAULT NULL,
  `VALUE` int(2) DEFAULT NULL,
  PRIMARY KEY (`ID_CF`)
)

我需要以excel格式导出所有这些数据,例如:

Id:st / Name / Subject1/ Subject2/ Subject3/ Subject4/..../Subject_N(如果一个学生没有某个科目的资格,则excel显示此专栏的空单元格。)

我如何加入所有这些表格?我考虑过使用LEFT JOIN,但此查询的返回行数呈指数增长。

现在我的问题比以前更糟了,因为我必须添加与1:N基数的学生相关的新表。

我该如何改进此功能?我无法更改数据库架构。

由于

1 个答案:

答案 0 :(得分:1)

我想你忘了GROUP BY,请尝试以下方法。

SELECT
    ST.ID_ST, ST.`NAME`, GROUP_CONCAT(DISTINCT SU.`NAME`) AS subjects
FROM STUDENTS AS ST
LEFT JOIN QUALIFICATIONS AS QU ON
    ST.ID_ST = QU.ID_ST
LEFT JOIN SUBJECTS AS SU ON
    SU.ID_SB = QU.ID_SB
GROUP BY ST.ID_ST

这应该只显示每个学生一次,主题应该用逗号(,)分隔,每个主题应该只出现一个学生一次(但只有学生有主题)。

ID - 姓名 - 主题
1 - Eve - Subj1,Subj3,Subj7

但是,这不是你要求的,你希望每个主题都拥有它自己的专栏,对吗?

为此,您可以在选择中使用subquery来获取所有主题,并使用IF为每个主题打印是或否。您仍然需要使用GROUP_CONCAT。但我会以不同的方式解决它。

我会使用不同的语言来分隔列。首先,您需要所有学生科目的学生信息和ID,如下所示:

SELECT
    ST.ID_ST, ST.`NAME`, GROUP_CONCAT(DISTINCT QU.`ID_SB`) AS subject_ids
FROM STUDENTS AS ST
LEFT JOIN QUALIFICATIONS AS QU ON
    ST.ID_ST = QU.ID_ST
GROUP BY ST.ID_ST

然后得到主题:

SELECT * FROM SUBJECTS

最后一部分是创建Excel。下面的例子是用PHP编写的:

$excelRows = array();
foreach($students as $student){
    $excelRow = array($student->id, $student->name);
    foreach($subjects as $subject){
        array_push($excelRow, (in_array($subject->id, $student->subject_ids))?'yes':'no');
    }
    array_push($excelRows, $excelRow);
}

所以,我们只是循环学生,在学生循环中我们循环主题。

它没有经过测试,但我认为大部分都应该有效。如果失败了,请告诉我你的尝试并解释它为什么不起作用。