简体   繁体   中英

Add second (conditional) result from second table to SQL query

I have two tables in a database. One stores names/details of users with an index ID; the other stores articles they have written, which just keeps the user's ID as a reference (field author ). So far so simple. I can easily query a list of articles and include in the query a request for the user's name and status:

SELECT a.name, a.status, s.* FROM articles s, author a WHERE s.author=a.id

The problem comes when I occasionally have a second author credit, referenced in field author2 . Up till now I've been doing what I assume is a very inefficient second query when I iterate through the results, just to get the second author's name and status from the table (pseudocode):

while ( fetch a row ) {
    if (author2 != 0) {
        query("SELECT name, status FROM author WHERE id=author2") }
    etc. }

While this worked fine in PHP/MySQL (even if clunky), I'm forced to upgrade to PHP7/PDO and I'd like to get the benefits of unbuffered queries, so this nested query won't work. Obviously one simple solution would be to PDO->fetchALL() the entire results first before iterating all the result rows in a foreach loop and doing these extra queries per row.

But it would be far more efficient to get that second bit of data somehow incorporated into the main query, pulling from the author table using the second ID ( author2 ) as well as the main ID, so that there are name2 and status2 fields added to each row. I just cannot see how to do it...

It should be noted that while the primary author ID field is ALWAYS non-zero, the author2 field will contain zero if there is no second ID, and there is NO author ID 0 in the author table, so any solution would need to handle an author2 ID of 0 by providing null strings or something in those fields, rather than giving an error. (Or far less elegantly, a dummy author ID 0 with null data could be added to the author table, I suppose.)

Can anyone suggest a revised original query that can avoid such secondary queries?

Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax.

For your query, use LEFT JOIN :

SELECT s.*, a1.name, a1.status, a2.name, a2.status
FROM articles s LEFT JOIN
     author a1
     ON s.author = a1.id LEFT JOIN
     author a2
     ON s.author2 = a2.id

Gordon Linoff's answer looks like what you need.

I would have added this as a comment but it is too long of a message...

I just have a question/comment regarding normalization of the database. Would there ever be an instance when there is an author3? If so then you should probably have an ArticleAuthor table. Since you are rebuilding the code anyway this may be an improvement to consider.

I don't know the names and data types of the information you are storing so this is a primitive example of the structure I would suggest.

Table Article
ArticleID
ArticleData...

Table Author
AuthorID
AuthorName
AuthorStatus

Table ArticleAuthor
ArticleID
AuthorID

If the Status is dependent on the Author Article combination then AuthorStatus would be moved to ArticleAuthor table like this.

Table ArticleAuthor
ArticleID
AuthorID
Status

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