How do I limit the query by two custom meta fields, a start date and an end date? This is what my data looks like:

meta_key   | meta_value |
start_date | 20100131   | //Jan 15, 2010
end_date   | 20100206   | //Feb 6, 2010

$today = date(YYYYMMDD);

The post will show if start_date = $today and it will expires when end_date = $today.


Here is the structure on my single.php

First Query I use here your answer

query_posts( $query_string );
if (have_posts()) : while (have_posts()) : the_post();
    ?><a href="<?php the_permalink() ?>"><?php the_title() ?></a><br /><?php
endwhile; endif;

and Second Query with regular wordpress function but this second query doesnt work properly

if (have_posts()) : while (have_posts()) : the_post();
    ?><a href="<?php the_permalink() ?>"><?php the_title() ?></a><br /><?php
endwhile; endif;

2 Answers 2


Edited again to demonstrate adding and removing filters:

Include these general functions in your functions.php. These are the filters you will invoke for the loops where you want to limit your query by these two meta values:

function date_check_join( $join ) {
    global $wpdb;
    $join .= " JOIN ".$wpdb->postmeta." AS startdate ON 
        (".$wpdb->posts.".ID = startdate.post_id AND
        startdate.meta_key = 'start_date')
        JOIN ".$wpdb->postmeta." AS enddate ON 
        (".$wpdb->posts.".ID = enddate.post_id AND
        enddate.meta_key = 'end_date')";
    return $join;

function date_check_where( $where ) {
    $today = date('Ymd');
    $where .= " AND startdate.meta_value <= $today
    AND enddate.meta_value >= $today";
    return $where;

Now, on the page(s) where you want to include these filters, add them before the loops you want to filter and remove them afterward. For example:

add_filter( 'posts_join', 'date_check_join' );
add_filter( 'posts_where', 'date_check_where' );

query_posts( "yourqueryhere" );
if (have_posts()) : while (have_posts()) : the_post();
// This loop will only includes where today is between start_date and end_date
endwhile; endif;

query_posts( "anotherqueryhere" );
if (have_posts()) : while (have_posts()) : the_post();
// This loop also only includes where today is between start_date and end_date
endwhile; endif;

remove_filter( 'posts_join', 'date_check_join' );
remove_filter( 'posts_where', 'date_check_where' );

query_posts( "thirdqueryhere" );
if (have_posts()) : while (have_posts()) : the_post();
// This loop is not affected by the filters, so you can query for posts 
// where start_date is in the future, or end_date in the past, etc.
endwhile; endif;

You just need to add your conditions to the 'posts_join' and 'posts_where' filters before your search, and remove them afterwards (otherwise these conditions will be applied to everything on your site, including pages, menus, etc.)

If you can simplify this by only comparing against one field, then you can use the meta_compare attribute built into the WP_Query object. You could schedule your posts for the start_date (so they don't show ahead of schedule), and then compare the date against the end_date custom field when you query.

  • @Jan Fabry thanks for editing my post it was exactly what I want
    – Gerald
    Jan 17, 2011 at 9:02
  • @goldenapples thanks for the answer. I tested the script above but it have an error here is at line 3 Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING
    – Gerald
    Jan 17, 2011 at 9:03
  • @Gerald Oh. I left out a comma from the second line above. Try it now. I did test it out on my local server and I can confirm that it does work. Jan 17, 2011 at 18:46
  • @goldenapples thank you! got it..but another issue it filter also the post in admin post listng.. .how what we can do so it will not affect the post list in admin side.. thanks
    – Gerald
    Jan 18, 2011 at 8:07
  • @Gerald Ah... you're adding this code straight in your functions.php file. I was thinking that you would add these filters right before the loop you wanted to filter, then remove them afterward. If you want to filter all the loops on your site this way, then hook the filters onto something and test whether you're in the admin section or not before applying them. I'll edit my answer to give an example. Jan 18, 2011 at 17:00

The answer to this question: How to Change Loop to Order Posts by Views (using wp-postviews plugin) shows you how to sort by a custom field.

Take a look at the Codex docs for query_posts(): http://codex.wordpress.org/Template_Tags/query_posts, and look a the custom field sections.

Then, all you need to do is include a test within the loop to skip if ($today < start_date or $today > end_date)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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