Mysql 多表上的复杂SQL查询

Mysql 多表上的复杂SQL查询,mysql,sql,Mysql,Sql,我有以下数据库架构: 使用下面的SQL -- ----------------------------------------------------- -- Table `gr_reports` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `gr_reports` ( `id` BIGINT(10) NOT NULL AUTO_INCREMENT, `cohor

我有以下数据库架构:

使用下面的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;
事实上,数据库包含gr_报告,每个gr_报告包含一些课程项目(gr_课程)作为报告车的行,gr_成绩作为报告车的列。与以下内容类似:

.------.-------.-------.------
|      |  mid  | final |  ...
|------|-------|-------|------
| math |   9   |   7   |  ...
|------|-------|-------|------
| ...
请注意,我删除了此处的“课程”和“成绩”选项卡,以简化我的图表,该图表独立于此部分创建,其信息在单独的表格中

出于某种原因,gr_课程中的每个记录都与gr_课程列表中的许多(1:N)课程相关。例如,“数学”项可能与“课程”表中的“数学1”和“数学2”相关。最后,gr_成绩列表将每个成绩项目与课程项目联系起来

现在我的问题是: 对于该报告中的每个报告和每个课程,有多少等级标题未设置在gr_等级列表中。我的意思是等级项目没有映射到“等级”选项卡中的对应项

我在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

这将给出正确的结果():


当在
WHERE
子句中有列
course\u id
时,无需
LEFT JOIN courses\u list
(如果不匹配,
course\u id
NULL,该行将被过滤掉)。
gr\u grades\u列表的
左连接
乘以
gr\u grades.id
计数
(可以在您的查询中使用
计数(DISTINCT gr\u grades.id)
,但是
gr\u grades\u列表的
计数
DISTINCT
仍然是错误的).

示例数据和SQL FIDLE将帮助其他人理解您的问题。您是否打算在
关键字上为其中一些
编写
?看到您添加了示例,我不得不更改我的答案,现在它可以工作了(已测试)。
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