我建议 3 个表,但不是您定义的 3 个。
students 和 users 表只是相互复制,因此这两个表可以成为 1 个表。
课程表没有问题。
第三个表是用于将学生映射/关联/关联到课程的表,并允许多对多类型的关系。也就是说,一个学生可以有很多课程,每门课程可以有很多学生。
所以表格可以是:-
table_users(id, name, 其他列,如果需要的话)
table_courses(code, title) (其中代码是唯一的)
table_user_course (studentId, courseCode)
也许考虑以下演示如何使用上述内容,包括两个包含使用关系的查询:-
/* Recreate tables if they exist */
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS courses;
DROP TABLE IF EXISTS user_courses;
CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE IF NOT EXISTS courses (code TEXT PRIMARY KEY, title);
CREATE TABLE IF NOT EXISTS user_courses(userId INTEGER, courseCode INTEGER, PRIMARY KEY(userID,courseCode));
/* Add some testing data */
INSERT INTO users (name) /*<<<< Let sqlite generate the id so just insert the 1 value for name */
VALUES ('Mary') /* Mary will be id 1 */,('Fred') /* Fred will be id 2 */,('Sue') /* Sue will be id 3 */
;
INSERT INTO courses /* no need to define columns to insert into as all columns */
VALUES ('M100','Mathematics'),('E100','English Language'),('S100','Science'),('G100','Geography')
;
INSERT INTO user_courses
VALUES
(1,'M100'),(1,'S100') /* Mary enrolled in maths and science */,
(3,'G100'),(3,'E100'),(3,'S100') /* Sue in Geog, English and science */,
(2,'M100'),(2,'E100'),(2,'S100') /* Fred in Maths, English andd Science */
;
SELECT name, code, title FROM users JOIN user_courses ON userID = id JOIN courses ON code = courseCode ORDER BY name;
SELECT title, count() AS enrolled, group_concat(name)
FROM courses
JOIN user_courses ON user_courses.courseCode = courses.code
JOIN users ON users.id = user_courses.userId
GROUP BY courses.code
;
/* Cleanup testing environment */
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS courses;
DROP TABLE IF EXISTS user_courses;
第一个查询,根据 (ODRER BY) 列出相关行的名称(映射表仅用于不显示值,因为它们对最终用户几乎没有用处)
第二个查询利用一些聚合函数,这些函数根据所选行的分组方式 (GROUP BY)(分为子集)组合值。按课程分组。 count 函数返回集合中的行数,group_concat 函数返回一个逗号分隔的列表,其中包含指定表达式(通常是一列)中的所有值设置。