Search code examples
sqlsubquery

Outer SELECT takes the first result of the nested SELECT


I am trying to get the courses where the last action (state) of the employee with the course is "enrolled"

This is the table of all courses

CREATE TABLE course (
    id integer primary key,
    name text
);

This is the table of all employees, nid = NationalID

CREATE TABLE employee (
    id integer primary key,
    nid integer,
    name text
);

This a table where I record all actions of employees with all courses

CREATE TABLE tran (
    id integer primary key,
    nid integer,
    cid integer,
    state text
);

Here's my data

INSERT INTO course VALUES (1, "c1"); --> required result
INSERT INTO course VALUES (2, "c2");
INSERT INTO course VALUES (3, "c3"); --> required result

INSERT INTO employee VALUES (1, 111, "e1");
INSERT INTO employee VALUES (2, 222, "e2");
INSERT INTO employee VALUES (3, 333, "e3");

INSERT INTO tran VALUES (1, 111, 1, "enrolled"); --> latest action
INSERT INTO tran VALUES (3, 222, 3, "enrolled");
INSERT INTO tran VALUES (4, 222, 3, "rejected");
INSERT INTO tran VALUES (5, 111, 2, "enrolled");
INSERT INTO tran VALUES (6, 111, 2, "withdrawn");
INSERT INTO tran VALUES (7, 111, 3, "enrolled"); --> latest action

I'm supposed to get the rows I marked above

I can get the latest action with each course using this

SELECT cid FROM tran AS t1
WHERE t1.id = (
    SELECT MAX(t2.id) FROM tran AS t2
    WHERE t1.nid = 111
    AND t1.cid = t2.cid
)
AND t1.state = "enrolled";

Output: 
1
3

But when I try to wrap it with another SELECT statement to get the names of the courses, I only get the first one

SELECT id, name FROM course AS c
WHERE c.id = (
    SELECT cid FROM tran AS t1
    WHERE t1.id = (
        SELECT MAX(t2.id) FROM tran AS t2
        WHERE t1.nid = 111
        AND t1.cid = t2.cid
    )
    AND t1.state = "enrolled"
);

Output: 
1|c1

Solution

  • At first glance, you might try the IN operator.

    SELECT id, name FROM course AS c
    WHERE c.id IN (
        SELECT cid FROM tran AS t1
        WHERE t1.id = (
            SELECT MAX(t2.id) FROM tran AS t2
            WHERE t1.nid = 111
            AND t1.cid = t2.cid
        )
        AND t1.state = "enrolled"
    );
    

    Haven't tested it myself, however.