简体   繁体   中英

MySQL Filter Many-to-Many

I have the following tables:

CREATE TABLE `job_requirements` (
  `job_id` INT(10) UNSIGNED NOT NULL,
  `course_id` INT(10) UNSIGNED NOT NULL,
  PRIMARY KEY (`job_id`,`course_id`)
)

CREATE TABLE `courses_completed` (
  `courseId` INT(10) UNSIGNED NOT NULL,
  `userId` INT(10) UNSIGNED NOT NULL,
  `completionDate` BIGINT(20) UNSIGNED NOT NULL,
  `completionStatus` INT(10) UNSIGNED NOT NULL,
  PRIMARY KEY (`courseId`,`userId`,`completionDate`)
)

A user can complete a course multiple times with various completionStatuses. A job can have multiple requirements. How can I get a list of all users who have completed (completionStatus = 1) all the required courses for a job?

The best I've come up with is a query that returns how many required, non-expired courses a user has completed:

SELECT COUNT(*) FROM 
    (
        SELECT courseId FROM courses_completed
        INNER JOIN courses ON courseId = courses.id
        WHERE completionStatus = 1
        AND courseId IN (
            SELECT course_id FROM job_requirements
            WHERE job_id = 1)
        AND userId = 23
        AND (FROM_UNIXTIME(completionDate)
             + INTERVAL expiration_days DAY
             + INTERVAL expiration_months MONTH
             + INTERVAL expiration_years YEAR) > NOW()
        GROUP BY courseId
    ) AS sub;

And a query that returns a list of users that have completed any of the required courses:

SELECT userId
FROM courses_completed WHERE courseID 
IN 
(
    SELECT course_id 
    FROM job_requirements
    WHERE job_id = 1
) GROUP BY userId;

I can't figure out how to combine the two so the userId from each row in the 2nd query is passed into the first query

Use a JOIN

SELECT userId
FROM (
    SELECT userId, COUNT(*) AS courses_completed
    FROM courses_completed AS cc
    JOIN job_requirements AS jr ON cc.courseID = jr.courseID
    WHERE jr.job_id = 1
    AND cc.completionStatus = 1
    AND (FROM_UNIXTIME(completionDate)
         + INTERVAL expiration_days DAY
         + INTERVAL expiration_months MONTH
         + INTERVAL expiration_years YEAR) > NOW()
    GROUP BY userId) AS u
JOIN (
    SELECT COUNT(*) AS courses_required
    FROM job_requirements
    WHERE job_id = 1) AS j
ON u.courses_completed = j.courses_required

You could also do this without a JOIN , but this structure allows you to extend it to multiple jobs. Take job_id = 1 out of both WHERE clauses, and add it to the SELECT and GROUP BY clauses, as well as the final ON` clause.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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