I had a similar problem recently, I needed to get 7 pieces of metadata from a custom post type, but also needed to get the post based on a piece of metadata.
So I created the following SQL statement, I use it often.
Hopefully it will help someone else. I'll try and explain it as best I can.
global $wpdb;
$pt = 'clients';
$mk = 'trainerid';
$mv = $pid;
$mk1 = 'email';
$mk2 = 'phone';
$mk3 = 'gender';
$mk4 = 'dob';
$mk5 = 'photo';
$mk6 = 'registrationts';
$mk7 = 'activationts';
$ord = 'p.post_name ASC';
$sql = "
SELECT p.ID, p.post_title AS fullname, pm1.meta_value AS email, pm2.meta_value AS phone, pm3.meta_value AS gender, pm4.meta_value AS dob, pm5.meta_value AS photo, pm6.meta_value AS regts, pm7.meta_value AS actemailts
FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
AND pm.meta_key = '{$mk}'
LEFT JOIN {$wpdb->postmeta} pm1 ON pm1.post_id = p.ID
AND pm1.meta_key = '{$mk1}'
LEFT JOIN {$wpdb->postmeta} pm2 ON pm2.post_id = p.ID
AND pm2.meta_key = '{$mk2}'
LEFT JOIN {$wpdb->postmeta} pm3 ON pm3.post_id = p.ID
AND pm3.meta_key = '{$mk3}'
LEFT JOIN {$wpdb->postmeta} pm4 ON pm4.post_id = p.ID
AND pm4.meta_key = '{$mk4}'
LEFT JOIN {$wpdb->postmeta} pm5 ON pm5.post_id = p.ID
AND pm5.meta_key = '{$mk5}'
LEFT JOIN {$wpdb->postmeta} pm6 ON pm6.post_id = p.ID
AND pm6.meta_key = '{$mk6}'
LEFT JOIN {$wpdb->postmeta} pm7 ON pm7.post_id = p.ID
AND pm7.meta_key = '{$mk7}'
WHERE pm.meta_value = '{$mv}'
AND p.post_type = '{$pt}'
AND p.post_status NOT IN ('draft','auto-draft')
ORDER BY {$ord}
";
$clients = $wpdb->get_results( $wpdb->prepare( $sql ), OBJECT );
First I get the wordpress database functions with global $wpdb.
Then I set the posttype with $pt.
To get the correct post that matches a specific value in post_meta, I set the $mk (meta_key)
Then I set the $mv (meta_value) var. (in this case the meta value matches a postid)
$mk1-$mk7 are the meta_keys I want from each post. (I'll grab the values in the select statement)
I also make the 'order by' a var, by setting $ord
The select statement goes as follows:
I select the post ID and the post_title from the POST or 'p.'
Then I select all the metadata I need selecting them with pm1. -> pm.7 and grabbing the meta_value and renaming them ( AS ) so it's more readable when retrieving the data from my object.
I create a LEFT JOIN for the meta data I need to match to the post. (pm)
I create 7 left join's for each of the meta data I need to retrieve. (pm1-pm7)
The WHERE statement is based on the first LEFT JOIN (pm) so that it will know I need only the posts where the metadata matches.
I also add an 'AND' for the post type, and for the post_statuses that are not drafts. (so only published posts)
Finally I add the 'order by' clause.
This works fast and with the built-in indexes in Wordpress, so it seems efficient.
Don't know if something is better than this, but if it is, I'd love to use it.
Hope this helps.
Marcus
get_post_meta
on individual keys, 2) runget_post_custom
to get all of a posts custom fields in one shot, or 3) create your own query using the $wpdb class (get_results()
) to build your own return object. ($wpdb class documentation: codex.wordpress.org/Class_Reference/wpdb)