I want to list all records in a mysql master table and only the last record in the related child table. Here is the code. But it outputs only the matched records for two tables of PK. Not lists the rest of records in the master
SELECT contact.id, contact.title, contact.init, contact.first_name, contact.last_name, contact.city, contact.home_phone, contact.mobile_phone, contact.e_mail, status.status AS status, fundsource.fundsource AS fundsource, category.category AS category,contact.score, ROUND(value/1000000,1) AS value_M, jstate.jstate AS to_do, journal.l_date AS last_activity, journal.note AS journal FROM contact
LEFT JOIN journal ON journal.con_id=contact.id
LEFT JOIN jstate ON jstate.jstate_code=journal.jstate_code
LEFT JOIN category ON category.cat_code=contact.cat_code
LEFT JOIN status ON status.st_code=contact.st_code
LEFT JOIN fundsource ON fundsource.fundsource_code=contact.fundsource_code
WHERE journal.l_date=(SELECT MAX(journal.l_date) from journal WHERE journal.con_id = contact.id) GROUP BY contact.id
Can anyone help me? Pls
The problem you're getting is because you've set criteria on one of the fields in a LEFT JOIN table, so your WHERE clause basically negates the LEFT JOIN.
The LEFT JOIN says: "Give me everything in contact, and if there's a matching row in journal, give me that too"
Then you've added criteria which says, "Once you've done that, only give me the rows where journal.l_date is the latest".
Which basically excludes anything where journal.l_date is missing, thus filtering out all of the contact records without journal entries.
You need to introduce the option for that record not being there.
There are two ways you can do this, depending on the database you're using.
SELECT contact.id, contact.title, contact.init, contact.first_name, contact.last_name, contact.city, contact.home_phone, contact.mobile_phone, contact.e_mail, status.status AS status, fundsource.fundsource AS fundsource, category.category AS category,contact.score, ROUND(value/1000000,1) AS value_M, jstate.jstate AS to_do, journ.l_date AS last_activity, journ.note AS journal FROM contact LEFT JOIN (SELECT * FROM journal WHERE journal.l_date=(SELECT MAX(journal.l_date) from journal WHERE journal.con_id = contact.id) ) as journ LEFT JOIN jstate ON jstate.jstate_code=journ.jstate_code LEFT JOIN category ON category.cat_code=contact.cat_code LEFT JOIN status ON status.st_code=contact.st_code LEFT JOIN fundsource ON fundsource.fundsource_code=contact.fundsource_code GROUP BY contact.id
You can see I"ve moved your criteria into a sub-select within the left join, and I've given that filtered table an alias journ
(I've done this by eye, so you might need to verify it by running it against your database).
This is the way that I'd prefer to do it.
Some databases might not like this syntax though.
`
SELECT contact.id, contact.title, contact.init, contact.first_name, contact.last_name, contact.city, contact.home_phone, contact.mobile_phone, contact.e_mail, status.status AS status, fundsource.fundsource AS fundsource, category.category AS category,contact.score, ROUND(value/1000000,1) AS value_M, jstate.jstate AS to_do, journal.l_date AS last_activity, journal.note AS journal FROM contact
LEFT JOIN journal ON journal.con_id=contact.id
LEFT JOIN jstate ON jstate.jstate_code=journal.jstate_code
LEFT JOIN category ON category.cat_code=contact.cat_code
LEFT JOIN status ON status.st_code=contact.st_code
LEFT JOIN fundsource ON fundsource.fundsource_code=contact.fundsource_code
WHERE (
(journal.con_id IS NULL)
OR ( journal.l_date=(SELECT MAX(journal.l_date) from journal WHERE journal.con_id = contact.id)
)
GROUP BY contact.id
`
You may have more luck with this option, depending on what your database supports.
Here I've allowed journal.con_id to be NULL, as a valid option, which matches the basic idea behind a LEFT JOIN a bit better.
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.