我有以下数据库架构:
使用以下SQL
-- -----------------------------------------------------
-- Table `gr_reports`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `gr_reports` (
`id` BIGINT(10) NOT NULL AUTO_INCREMENT,
`cohort_id` BIGINT(10) NOT NULL,
`title` LONGTEXT CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NOT NULL,
`allow_students` LONGBLOB NOT NULL,
`allow_parents` LONGBLOB NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
-- -----------------------------------------------------
-- Table `gr_courses`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `gr_courses` (
`id` BIGINT(10) NOT NULL AUTO_INCREMENT,
`report_id` BIGINT(10) NULL,
`title` LONGTEXT CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NOT NULL,
`weight` TINYINT(2) NOT NULL,
`sortorder` TINYINT(2) NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_report_id` (`report_id` ASC),
CONSTRAINT `fk_report_id`
FOREIGN KEY (`report_id`)
REFERENCES `gr_reports` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
-- -----------------------------------------------------
-- Table `gr_courses_list`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `gr_courses_list` (
`id` BIGINT(10) NOT NULL AUTO_INCREMENT,
`report_course_id` BIGINT(10) NOT NULL,
`course_id` BIGINT(10) NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_report_course_id` (`report_course_id` ASC),
UNIQUE INDEX `idx_unique_ids` (`course_id` ASC, `report_course_id` ASC),
CONSTRAINT `fk_g_report_course_id`
FOREIGN KEY (`report_course_id`)
REFERENCES `gr_courses` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
-- -----------------------------------------------------
-- Table `gr_grades`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `gr_grades` (
`id` BIGINT(10) NOT NULL AUTO_INCREMENT,
`report_id` BIGINT(10) NULL,
`title` VARCHAR(45) NULL,
`sortorder` TINYINT(2) NULL,
PRIMARY KEY (`id`),
INDEX `idx_report_id` (`report_id` ASC),
CONSTRAINT `fk_gr_grades_gr_reports1`
FOREIGN KEY (`report_id`)
REFERENCES `gr_reports` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `gr_grades_list`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `gr_grades_list` (
`id` BIGINT(10) NOT NULL AUTO_INCREMENT,
`report_grade_id` BIGINT(10) NOT NULL,
`course_item_id` BIGINT(10) NULL,
`grade_item_id` BIGINT(10) NULL,
PRIMARY KEY (`id`),
INDEX `idx_report_grade_id` (`report_grade_id` ASC),
UNIQUE INDEX `idx_unique_ids` (`grade_item_id` ASC, `report_grade_id` ASC, `course_item_id` ASC),
INDEX `idx_report_course_item_ids` (`course_item_id` ASC),
CONSTRAINT `fk_report_grade_id`
FOREIGN KEY (`report_grade_id`)
REFERENCES `gr_grades` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT `fk_report_course_item_id`
FOREIGN KEY (`course_item_id`)
REFERENCES `gr_courses_list` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
事实上,数据库包含 Grades_Reports (gr_reports),每个 Grade_Report 包含一些类(class)项目 (gr_courses) 作为报告车的行和成绩项目 (gr_grades) 作为报告车的列。类似于下面的:
.------.-------.-------.------
| | mid | final | ...
|------|-------|-------|------
| math | 9 | 7 | ...
|------|-------|-------|------
| ...
请注意,我在这里删除了“类(class)”和“成绩”标签,以简化我的图表,该图表独立于这部分创建,并将它们的信息放在单独的表格中。
由于某种原因,gr_courses 中的每条记录都与 gr_courses_list 中的许多 (1:N) 类(class)相关。例如,“math”项可能与“course”表中的“math1”和“math2”相关。最后 gr_grades_list 将每个成绩项目与类(class)项目相关联。
现在我的问题是: 对于每份报告和该报告中的每门类(class),有多少成绩标题尚未在 gr_grades_list 中设置。我的意思是成绩项目没有映射到它在“成绩”标签中的对应项。
我在 mysql 中尝试了以下查询,但结果不正确:
SELECT
gr_reports.id,
gr_reports.title,
gr_courses.title,
count(gr_grades.id),
count(gr_grades_list.id)
FROM gr_reports
JOIN (gr_courses LEFT JOIN gr_courses_list
ON gr_courses_list.report_course_id = gr_courses.id)
ON gr_courses.report_id = gr_reports.id
JOIN (gr_grades LEFT JOIN gr_grades_list
ON gr_grades_list.report_grade_id = gr_grades.id)
ON gr_grades.report_id = gr_reports.id
WHERE gr_courses_list.course_id=145
group by gr_reports.id, gr_courses.id
编辑:
对于下面的示例数据
INSERT INTO gr_reports
(id, cohort_id, title, allow_students, allow_parents)
VALUES (1, 1, 'report1', 0, 0), (2, 1, 'report2', 0, 0);
INSERT INTO gr_courses
(id, report_id, title, weight, sortorder)
VALUES (1, 1, "r1_c1", 1, 0), (2, 1, "r1_c2", 1, 1),
(3, 2, "r2_c1", 1, 0), (4, 2, "r2_c2", 1, 1);
INSERT INTO gr_courses_list
(id, report_course_id, course_id)
VALUES (1, 1, 145),(2, 1, 146),(3, 2, 145),(4, 2, 147),
(5, 3, 145),(6, 3, 148),(7, 4, 145),(8, 4, 149);
INSERT INTO gr_grades
(id, report_id, title, sortorder)
VALUES (1, 1, "r1_g1", 0), (2, 1, "r1_g2", 1),
(3, 2, "r2_g1", 0), (4, 2, "r2_g2", 1);
INSERT INTO `moodle`.`gr_grades_list`
(id, report_grade_id, course_item_id, grade_item_id)
VALUES (1, 1, 1, 505),(2, 2, 1, 506),(3, 1, 3, 507),
(4, 2, 3, 508), (5, 3, 5, 509);
结果应该类似于:
1, report1, r1_c1, 2, 2
1, report1, r1_c2, 2, 2
2, report2, r2_c1, 2, 1
2, report2, r2_c2, 2, 0
最佳答案
这将给出正确的结果(SQLFiddle):
SELECT
gr_reports.id,
gr_reports.title,
gr_courses.title,
COUNT(gr_grades.id),
(SELECT COUNT(1) FROM gr_grades_list WHERE gr_grades_list.report_grade_id = gr_courses.id)
FROM gr_reports
JOIN gr_courses ON gr_courses.report_id = gr_reports.id
JOIN gr_grades ON gr_grades.report_id = gr_reports.id
JOIN gr_courses_list ON gr_courses_list.report_course_id = gr_courses.id
WHERE gr_courses_list.course_id = 145
GROUP BY gr_reports.id, gr_courses.id
不需要 LEFT JOIN courses_list
当你有它的列 course_id
在WHERE
子句(如果没有匹配项,course_id
就是 NULL
并且该行将被过滤掉)。 LEFT JOIN
与 gr_grades_list
乘以 COUNT
的 gr_grades.id
(可以在您的查询中使用 COUNT(DISTINCT gr_grades.id)
修复,但是 COUNT
的 gr_grades_list
仍然是 DISTINCT
的错误)。
关于mysql - 对多个表的复杂 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33677062/