简体   繁体   English

多个表上的复杂SQL查询

[英]Complex SQL query over multiple table

I have the following database schema: 我有以下数据库架构:

数据库架构

with the folowing SQL 与下面的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;

In fact the database contains Grades_Reports (gr_reports) and each Grade_Report contains some Courses items (gr_courses) as row of report cart and Grades items(gr_grades) as columns of report cart. 实际上,数据库包含Grades_Reports(gr_reports),每个Grade_Report包含一些课程项目(gr_courses)作为报告购物车行和等级项目(gr_grades)作为报告购物车列。 Similar to the following one: 类似于以下内容:

.------.-------.-------.------
|      |  mid  | final |  ...
|------|-------|-------|------
| math |   9   |   7   |  ...
|------|-------|-------|------
| ...

Note, I remove ''course'' and ''grade'' tabels here to simplify my diagram which created independ of this part and have their informations in seperated tables. 请注意,我在这里删除了“'course''和''grade''表格,以简化我的图表,该图表创建了独立的部分,并在分离的表格中显示了它们的信息。

For some reason, Each record in gr_courses related to many (1:N) courses in gr_courses_list. 出于某种原因,gr_courses中的每条记录都与gr_courses_list中的许多(1:N)课程相关。 For example ''math'' item may related to ''math1'' and ''math2'' in ''course'' table. 例如,''math''项可能与''course''表中的''math1''和''math2''相关。 Finally gr_grades_list relate each Grade item to Course items. 最后,gr_grades_list将每个成绩项目与课程项目相关联。

NOW my question is: for each report and each course in that report how many of grades titles have not set in gr_grades_list. 现在我的问题是:对于每个报告和该报告中的每个课程,有多少成绩未在gr_grades_list中设置。 I mean the grade item is not map to its correspondance in ''grades'' tabel. 我的意思是成绩项目没有映射到“成绩”表格中的对应关系。

I try the follwing query in mysql but the result is not true: 我在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

EDIT: 编辑:

For the following sample data 对于以下示例数据

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);

The result should be similar to: 结果应类似于:

1, report1, r1_c1, 2, 2
1, report1, r1_c2, 2, 2
2, report2, r2_c1, 2, 1
2, report2, r2_c2, 2, 0

This will give the correct result ( SQLFiddle ): 这将给出正确的结果( 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

No need to LEFT JOIN courses_list when you have its column course_id in the WHERE clause (where there is no match, course_id is NULL and the row will be filtered out). 当你在WHERE子句中有它的course_id列时(如果没有匹配,则course_idNULL并且该行将被过滤掉),则无需LEFT JOIN courses_list The LEFT JOIN with gr_grades_list multiplied the COUNT of the gr_grades.id (could be fixed in your query with COUNT(DISTINCT gr_grades.id) , but the COUNT of gr_grades_list would still be wrong with DISTINCT ). LEFT JOINgr_grades_list乘以COUNT中的gr_grades.id (可固定在与您的查询COUNT(DISTINCT gr_grades.id)COUNTgr_grades_list仍然是错误的DISTINCT )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM