Reputation: 11702
First I would like to mention I have limited skills when it comes to MYSQL an JOIN. However this is what I have and what I like to achieve:
I have the default WordPress tables and like to get a result with post_name, title, status and the meta_value from a certain meta key.
This is what I have:
SELECT
wp_posts.ID, wp_posts.post_name, wp_posts.post_title, wp_posts.post_status, wp_postmeta.meta_value
FROM wp_posts
INNER JOIN
wp_term_relationships ON ( wp_posts.ID = wp_term_relationships.object_id )
INNER JOIN
wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
WHERE (
wp_term_relationships.term_taxonomy_id
IN ( 1, 2, 3 )
)
AND wp_posts.post_type = 'my_post_type'
AND (
wp_posts.post_status
IN (
'my_status_1', 'my_status_2'
)
)
AND wp_postmeta.meta_key = 'my_meta_key'
GROUP BY wp_posts.ID
ORDER BY wp_posts.ID ASC
Everything works as expected when each post has a postmeta of 'my_meta_key'. But if the 'my_meta_key' is missing the post is not in the result.
I guess it' caused by the second INNER JOIN but as mentioned I have no idea what I should it replace it with.
I'm sure it's something simple
Upvotes: 0
Views: 2389
Reputation: 247860
Change the INNER JOIN
on the wp_postmeta
table to a LEFT JOIN
:
LEFT JOIN wp_postmeta
ON ( wp_posts.ID = wp_postmeta.post_id )
And move the WHERE
filter for the wp_postmeta
to the JOIN
condition.
So your query will be:
SELECT wp_posts.ID, wp_posts.post_name, wp_posts.post_title, wp_posts.post_status, wp_postmeta.meta_value
FROM wp_posts
INNER JOIN wp_term_relationships
ON ( wp_posts.ID = wp_term_relationships.object_id )
LEFT JOIN wp_postmeta
ON ( wp_posts.ID = wp_postmeta.post_id )
AND wp_postmeta.meta_key = 'my_meta_key'
WHERE wp_term_relationships.term_taxonomy_id IN ( 1, 2, 3 )
AND wp_posts.post_type = 'my_post_type'
AND wp_posts.post_status IN ('my_status_1', 'my_status_2')
GROUP BY wp_posts.ID
ORDER BY wp_posts.ID ASC
The INNER JOIN
syntax will only return rows that match in both tables. So if you do not have a matching row, you will not get any result. By changing that to a LEFT JOIN
, you will return all rows even if there is not a matching row in the wp_postmeta
table. If the row does not exist, then the values from the wp_postmeta
table will be null
.
Upvotes: 0
Reputation: 35343
The following returns
*
SELECT wp_posts.ID, wp_posts.post_name, wp_posts.post_title,
wp_posts.post_status, wp_postmeta.meta_value
FROM wp_posts
LEFT JOIN wp_term_relationships
ON wp_posts.ID = wp_term_relationships.object_id
LEFT JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_term_relationships.term_taxonomy_id IN ( 1, 2, 3 )
AND wp_posts.post_type = 'my_post_type'
AND wp_posts.post_statusIN ('my_status_1', 'my_status_2')
AND (wp_postmeta.meta_key = 'my_meta_key' or wp_postmeta.meta_key is null)
GROUP BY wp_posts.ID
ORDER BY wp_posts.ID ASC
you need the is null otherwise records in wp_posts without wp_postmeta data will be excluded.
Upvotes: 0
Reputation: 1729
Move the AND wp_postmeta.meta_key = 'my_meta_key'
to
INNER JOIN
wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
Like this and change the INNER for a LEFT
LEFT JOIN
wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id
AND wp_postmeta.meta_key = 'my_meta_key')
If you put your condition in the "Where Clause" The Left join will be "overwritten". And I will add an advice. Dont use parenthesis when you dont really need it to keep your code easy to read.
Upvotes: 1