So for example I have two tables
Person Table
ID : Name
1 : Bob
2 : Jane
3 : Mike
4 : John
5: Mary
I then also have (current is actually an integer but I used text to make it more readable):
Job Table
ID : Name : PersonID : JobStatus
1 : Plumber : 1 : current
2 : Doctor : 2 : past
3 : Driver : 2 : current
4 : Cook : 3 : current
5: Programmer : 5 : past
I would like to join the two tables so that I can get a list of everyone, but I only want to include current jobs with the left join. In other words I want the result to be:
Bob : Plumber : current
Jane : Driver : current
Mike : Cook : current
John : :
Mary : :
How can I do this with a join. I tried doing:
SELECT
person.name, job.name, job.status
FROM
person
LEFT JOIN
job ON person.id=job.person.id
But the problem is that in this case I will see two entries for Jane, one for her past job of Doctor as well as her new job of Driver. And if I add a where clause such as:
WHERE job.status='current'
Then it removes removes John and Mary from the list.
How can I write a join that will show all the people yet only include jobs that are current?
At least in Oracle you should be able to do this:
SELECT
person.name, job.name, job.status
FROM
person
LEFT JOIN
job ON person.id=job.personId AND job.status = 'current';
so when person.id=job.person.id AND job.status = 'current'
the join is made, and when that condition is false you only get person
data.
I don't know if MySQL supports composite conditions in ON
clauses but I guess so, it is not exactly groundbreaking technology.
UPDATE:
Looks like it is supported, read https://dev.mysql.com/doc/refman/8.0/en/join.html
There are a few ways to do this; the best option depends on your database, and how the differing methods perform.
Method 1: Left Join with OR
SELECT p.name, j.name, j.status
FROM person AS p
LEFT JOIN job AS j ON j.personId = p.id AND j.status = 'current';
-- Returns all persons, and only jobs w/ value 'current'
-- If the filter on j.status were in the WHERE clause, it would remove non-matching
Method 2: Two queries with UNION ALL (this removes rows w/ no current or null vals)
SELECT p.name, j.name, j.status
FROM person AS p
INNER JOIN job AS j ON j.personId = p.id
WHERE j.status = 'current'
OR j.status IS NULL
UNION ALL
SELECT p.name, j.name, j.status
FROM person AS p
LEFT JOIN job AS j ON j.personId = p.id
WHERE j.status IS NULL;
Method 2b: Two queries with UNION ALL (this retains rows w/ no current or null vals)
SELECT p.name, j.name, j.status
FROM person AS p
INNER JOIN job AS j ON j.personId = p.id
WHERE j.status = 'current'
OR j.status IS NULL
UNION ALL
SELECT p.name, j.name, j.status
FROM person AS p
LEFT JOIN job AS j ON j.personId = p.id
WHERE NOT EXISTS
(SELECT 1 FROM jobs AS t WHERE t.personId=p.Id AND t.status='current')
GROUP BY p.Id;
-- GROUP BY ensures we only get one row back per person, but will be random if there are multiples
Method 3: Sub-selects
SELECT p.name, j.name, j.status
FROM person AS p
LEFT JOIN (
SELECT x.name
FROM job AS x
WHERE x.status = 'current'
) AS j;
Select p.name, j.name,j.status
From person p
Left Join
(Select name,status,personId
From job
Where status ='current'
) j On p.id = j.personId;
Can you try this query?
Try this
SELECT
person.name, job.name, job.status
FROM
person
LEFT JOIN
job ON person.id=job.person.id
WHERE CASE WHEN job.status IS NULL THEN '@' WHEN job.status ='current' THEN '@' else job.status END = '@'
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.