简体   繁体   中英

List all mysql records in a master table and last record in a related child table

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.

  1. Limit the matching rows in the join.

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.

  1. The other option is to leave the table as is in the JOIN phrase, but alter the criteria to enable the LEFT JOIN again:

`

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.

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