WP_Query multiple use of relation and/or

No, meta_query does not support these sorts of complex clauses in a sequence.

There are a couple of ways to work around this limitation.

  • One is to filter posts_where_paged and modify the SQL manually. I just spent a couple minutes playing with this option, and it’s not very straightforward – you’ll have to write a pretty sophisticated preg_replace() to get the parentheses grouped right, etc.

  • A more promising option is to get a whitelist of post ids manually, and then feed the results to the post__in parameter of WP_Query:

    global $wpdb;
    $post_ids = $wpdb->get_col( $wpdb->prepare( "
        SELECT post_id 
        FROM $wpdb->postmeta.pm 
        INNER JOIN $wpdb->postmeta.pm2 ON (pm.post_id = pm2.post_id)
        WHERE
            (pm.meta_key = 'status' AND pm.meta_value="1" 
            AND pm2.meta_key = 'start_date' AND pm2.meta_value >= '1332115200')
        OR
            (pm.meta_key = 'status' AND pm.meta_value="2")
    " ) );
    
    $query_args = array( 'post__in' => $post_ids ); // plus whatever else you want
    $my_query = new WP_Query( $query_args );
    

    When WP_Query assembles the SQL, your $post_ids get turned into a clause like: AND ID IN (1,2,3), which acts like a whitelist for whatever other parameters you pass to WP_Query.

Note that either way, this query is not going to be all that fast, since it requires some loose type casting on unindexed meta_value. Cache wisely 🙂

Leave a Comment