How can I limit number of posts per month in the loop as follows:

Today is June. In the loop there should be ten most popular posts (based on custom field page_views) for June and May, five for April, three for March and then one most popular post per month.

Thank you.

  • @s_ha_dum, i'm just trying to find out the concept. Don't see the point in posting the default WP_query loop based on sorting by a custom field.
    – Sergey
    Commented Jun 6, 2013 at 7:39
  • Ok, so you really haven't tried anything special.
    – s_ha_dum
    Commented Jun 6, 2013 at 12:54

1 Answer 1


WP_Query is not going to be able to perform a query of the complexity required to do this in one shot. What it would take to pick 10 from one month, ten form another, then 5 from another, then 3, then 1 like that is a number of UNIONs and WP_Query can't do that.

You have two choices that I can see:

  1. Hand write the SQL to pull your post IDs. This is not horribly complicated, but but not trivial. Then pass the post IDs through WP_Query as post__in to convert to post objects.
  2. Run a bunch of different queries, and Loops. Certainly the easiest solution. WP_Query accepts year and monthnum arguments.

For the first, you could save yourself some effort by doing something like this:

$qrypattern = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} 
INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)
WHERE 1=1  
AND {$wpdb->posts}.post_type = 'post' 
AND ({$wpdb->posts}.post_status = 'publish') 
AND ({$wpdb->postmeta}.meta_key = 'your_date'
AND {$wpdb->postmeta}.meta_value BETWEEN '%s' AND '%s')
GROUP BY {$wpdb->posts}.ID 
ORDER BY {$wpdb->postmeta}.meta_value ASC LIMIT %d";

$dates = array(
  array (
    's' => 'startdate',
    'e' => 'enddate',
    'c' => 10
  array (
    's' => 'startdate',
    'e' => 'enddate',
    'c' => 5
$union = array();
foreach ($dates as $v) {
  $union[] = '('.sprintf($qrypattern,$v['s'],$v['e'],$v['c']).')';
$qry = implode(' UNION ',$union );

Obviously, startdate and enddate are filler values. Those have to match your data. Hopefully that data is in some form that sorts appropriately-- UNIXTIME or YYYY-MM-DD, something like that.

No promises about the details of that query. I'd have to test it with real data to be certain it works correctly. Consider it an illustration only.

You could probably do something similar with filters but in this case I don't see the point. I think it would be more trouble than its worth.

  • Thanks for the answer. Variant 2 is not an option, because you can't combine several loops in one, hence pagination won't work. Variant 1 seems so complicated because it's working with DB directly. Thought there's some way to work with wordpress core functions.
    – Sergey
    Commented Jun 6, 2013 at 16:40
  • "...you can't combine several loops in one..." -- Yes you can: wordpress.stackexchange.com/a/99619/21376 , but if you need pagination this got many times more complicated.
    – s_ha_dum
    Commented Jun 6, 2013 at 16:57
  • Thank you for this tip! I don't think there'll be problems with pagination if you use this kind of combining two loops, are there any?
    – Sergey
    Commented Jun 10, 2013 at 4:50
  • Most pagination functions depend on the main query, and that query is the one that needs to know what page to load anyway, so it gets tricky with secondary Loops. How you handle that depends on details not provided in the question.
    – s_ha_dum
    Commented Jun 10, 2013 at 12:29

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.