3

I have the following database schema:

database schema

with the folowing 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. 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.

For some reason, Each record in gr_courses related to many (1:N) courses in gr_courses_list. For example ''math'' item may related to ''math1'' and ''math2'' in ''course'' table. Finally gr_grades_list relate each Grade item to Course items.

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. 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:

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
3
  • 2
    Sample data and a SQL Fiddle would help others understand your problem. Commented Nov 12, 2015 at 17:06
  • 1
    Did you mean to write AND for some of those ON keywords? Commented Nov 12, 2015 at 17:16
  • Saw you added examples, had to change my answer and it works now (tested). Commented Nov 12, 2015 at 20:02

1 Answer 1

1

This will give the correct result (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). 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 theCOUNT of gr_grades_list would still be wrong with DISTINCT).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.