WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am curious whether Wordpress is able to run nested meta_query, with each having different relation keys? As of Wordpress 3.0, tax_query is able to perform this function; I'm wondering whether this has an equivalent with meta_query.

$results = query_posts( array(
    'post_type' => 'event_id',
    'meta_query' => array(
        'relation' => 'AND',
            'relation' => 'OR',
                'key' => 'primary_user_id',
                'value' => $user_id
                'key' => 'secondary_user_id',
                'value' => $user_id
            'key' => 'date',
            'value' => array( $start_date, $end_date ),
            'type' => 'DATETIME',
            'compare' => 'BETWEEN'
) );


share|improve this question
up vote 10 down vote accepted

The question was for Wordpress 3.0, but just in case someone has the same question for a more recent version, from Wordpress Codex:

"Starting with version 4.1, meta_query clauses can be nested in order to construct complex queries."


So, that query should work on the current Wordpress version.

share|improve this answer

That seems to be impossible. Please someone correct me if I'm wrong.

The meta_query parameter will actually be transformed into a WP_Meta_Query object, and the relation verification won't go deeper in wp-includes/meta.php, and occurs just once in the top level:

if ( isset( $meta_query['relation'] ) && strtoupper( $meta_query['relation'] ) == 'OR' ) {
    $this->relation = 'OR';
} else {
    $this->relation = 'AND';

A possible solution for this is to build your own JOIN for this query.

$query = new WP_Query( array(
    'my_meta_query' => true,
    'suppress_filters' => false
) );

add_filter( 'posts_join', 'my_meta_query_posts_join', 10, 2 );
function my_meta_query_posts_join( $join, $query ) {

    if ( empty( $query->query_vars['my_meta_query'] ) )
        return $join;

    global $wpdb;

    $new_join = "
        INNER JOIN {$wpdb->postmeta} pm1 ON 1=1
            AND pm1.post_id = {$wpdb->posts}.ID
            AND pm1.meta_key = '_some_meta_key'
            AND pm1.meta_value = 'some_value'

    return $join . ' ' . $new_join;

And if you need further verifications and rules, you can also use the posts_where filter.

share|improve this answer
Seems to be the same approach @scribu recommends on Core Trac: core.trac.wordpress.org/ticket/20312 – Andrew Odri May 29 '14 at 19:49
@AndrewOdri it's the same but it's not =) – vmassuchetto Oct 6 '15 at 17:14

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.