Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have 2 custom fields that I would like to do a meta query on for a custom post type:

start_date
status

The outcome that I am looking for is

(start_date >= 1332115200 AND status = 1) OR (status = 2)

Is this possible to do with WP_Query?

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

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 :)

share|improve this answer
    
Thanks Boone. I will implement the second solution. Curious, how do you cache queries? –  pistolshrimp Mar 20 '12 at 0:52
1  
WP's Transients API is a nice way to do it, and it only takes a couple extra lines of code. wpbeginner.com/wp-tutorials/… is a decent introduction. The important part is to be sure that, in addition to setting a reasonable expiry date, you are sure to bust the cache (delete_transient()) when a new post is published with a 'start_date' or 'status' that needs to be counted in your query. –  Boone Gorges Mar 20 '12 at 1:22
    
That's exactly what I had in mind. Thanks so much!!! –  pistolshrimp Mar 20 '12 at 2:07
add comment

I think your answer is on this page, read the section, Order & Order By Paramaters.

In simple terms, ordering by meta_value means your query will have something like this in it

'orderby' => 'meta_value', 'meta_key' => 'your_meta_key'

... but to do something like the example you gave is a bit more tricky though I think you'll find it's actually explained under the heading "Multiple Custom Field Handling:". Read that in conjunction with the second part of "Custom Field Parameters" and you should eventually get it.

Pay attention to the arrays. I think you should end up with 3 nested arrays in your case.

share|improve this answer
add comment

Your Answer

 
discard

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.