Reputation: 29
I am new to SQL, so existing answers a bit complicated to me. I have three tables:
WORKER
|id
|name
|date
|...
JOB
|id
|name
|salary
|accept
APPOINTMENT
|id
|worker_id
|job_id
|date
So if worker was appointed several times in a year I need to know what work he had at some specified time.
I have something like this now:
SELECT w.name,w.id FROM worker w
INNER JOIN appointment a ON w.id = worker_id
INNER JOIN job j on job_id = j.id
WHERE accept = 1 AND a.date <= (SELECT date FROM orders WHERE id = 2);
Now it shows all appointments less or equal than some date, but I need only last one for each worker. How I need to modify it?
EDIT:
ORDER
|id
|accepted_by //worker_id
|...
Orders is used to just get date. It can be changed to any from any source. So it isn't important in this context. Accept in Job is just a bool value, it represents that appointed worker can accept new orders. So the full meaning for this is to show in edit form in ComboBox all workers that was able to accept an order (not just workers that can accept it now), when the order was created.
Date is represented as integer value of days from 1970. Lines that are pretend to be in output:
w.name w.id a.id a.date j.name j.accept
Smith 2 7 42999 administrator 1
Joe 1 6 42994 administrator 1
Smith 2 5 42994 waiter 0
Joe 1 4 42993 waiter 0
Smith 2 3 42992 administrator 1
Smith 2 2 42991 waiter 0
Smith 2 1 42990 administrator 1
What I receive with my query (it is listed above this edit) a.date <= 42998 and accept = 1;
Joe 1 6 42994 administrator 1
Smith 2 3 42992 administrator 1 //isn't current Smith's job
Smith 2 1 42990 administrator 1 //isn't current Smith's job
What I should to receive with my query a.date <= 42998;
//Last job in 42998
Joe 1 6 42994 administrator 1
Smith 2 5 42994 waiter 0
What I should to receive with my query a.date <= 42999;
//Last job in 42999
Smith 2 7 42999 administrator 1
Joe 1 6 42994 administrator 1
What I need to receive finally (a.date <= 42998 and accept=1):
//Workers which were able to accept order in 42998
Joe 1 6 42994 administrator 1
What I should to receive if (a.date <= 42999 and accept=1) ;
//Workers which were able to accept order in 42999
Smith 2 7 42999 administrator 1
Joe 1 6 42994 administrator 1
Tables (all unused fields are removed):
CREATE TABLE appointment (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, worker_id INTEGER NOT NULL, job_id INTEGER, date INTEGER NOT NULL);
CREATE TABLE worker (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,name TEXT NOT NULL);
CREATE TABLE job (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,name TEXT NOT NULL,accept INTEGER NOT NULL);
Inserts (like in example above):
INSERT INTO worker (name) VALUES ('Joe');
INSERT INTO worker (name) VALUES ('Smith');
INSERT INTO job (name,accept) VALUES ('waiter',0);
INSERT INTO job (name,accept) VALUES ('administrator',1);
INSERT INTO appointment (worker_id,job_id,date) VALUES (2,2,42990);
INSERT INTO appointment (worker_id,job_id,date) VALUES (2,1,42991);
INSERT INTO appointment (worker_id,job_id,date) VALUES (2,2,42992);
INSERT INTO appointment (worker_id,job_id,date) VALUES (1,1,42993);
INSERT INTO appointment (worker_id,job_id,date) VALUES (2,1,42994);
INSERT INTO appointment (worker_id,job_id,date) VALUES (1,2,42994);
INSERT INTO appointment (worker_id,job_id,date) VALUES (2,2,42999);
Upvotes: 1
Views: 37
Reputation: 180210
To get the last appointment for each worker, use grouping. Filter out the non-accepted ones in a second step:
SELECT ...
FROM (SELECT worker_id,
job_id,
MAX(date) AS date
FROM appointment
WHERE date <= ...
GROUP BY worker_id) AS a
JOIN worker AS w ON a.worker_id = w.id
JOIN job AS j ON a.job_id = j.id
WHERE accept = 1;
Upvotes: 1