I have three custom post type:

  • books
  • magazine
  • videos

Now i want to limit the number of post for custom post type, for example:

  • books => 3 post
  • magazine => 2 post
  • videos => 1 post

I used a query post like this:

query_posts( array(
    'post_type' => array(
'paged' => $paged,
'posts_per_page' => 6, 
$counter = 1;
if (have_posts()) :
    while (have_posts()) : the_post();  
if (($counter == 2) || ($counter == 3) || ($counter == 4)) {
        $div = 'alpha';
    } elseif(($counter == 6)) {
        $div = 'omega';
    } else {
        $div = '';

The problems is i cant limit the numbers by custom post type. Any idea?

Thank you :)

2 Answers 2


I hate writing "you can't do that" answers, but you can't. That is the strict answer to your question about whether you can do this with a single WP_Query. You can't limit post type counts individually in the same query using WP_Query (You are actually using query_posts. Please don't. It is not the right tool for secondary loops.)

Even in raw SQL you have to write separate queries and UNION them together, which is how I'd approach this.

$sql = "(SELECT ID FROM {$wpdb->posts} WHERE post_type = 'books' AND post_status = 'publish' LIMIT 3)
(SELECT ID FROM {$wpdb->posts} WHERE post_type = 'magazines' AND post_status = 'publish' LIMIT 2)
(SELECT ID FROM {$wpdb->posts} WHERE post_type = 'videos' AND post_status = 'publish' LIMIT 1)";
// be sure to add any other conditions you need
$ids = $wpdb->get_col($sql);

Then run those $ids through a new WP_Query to get the post objects you need for a proper Loop.

You could even break the SQL into a pattern and reuse it. Something like...

$sqlpat = "(SELECT ID FROM {$wpdb->posts} WHERE post_type = '%s' AND post_status = 'publish' LIMIT %d)";
$sql = '('.sprintf($sqlpat,'books',3).') UNION ALL ('.sprintf($sqlpat,'magazines',2).') UNION ALL ('.sprintf($sqlpat,'videos',1).')';

Assuming I didn't make a mistake (the code is not tested), you should then have what you want-- three post types each with a particular count. They may not come out in the order you want so you may have to sort them in PHP, or build an even trickier SQL query.


You can do this by merging queries:

$q1 = get_posts(array(
    'post_type' => 'books',
    'posts_per_page' => 3

$q2 = get_posts(array(
    'post_type' => 'magazines',
    'posts_per_page' => 2

$q3 = get_posts(array(
    'post_type' => 'videos',
    'posts_per_page' => 1

$merged = array_merge( $q1, $q2, $q3 );

$post_ids = array();
foreach( $merged as $item ) {
    $post_ids[] = $item->ID;

$unique = array_unique($post_ids);

$args = array(
    'post_type' => array(
    'post__in' => $unique,
    'post_status' => 'publish',
    'posts_per_page' => 6

$the_query = new WP_Query( $args );

while ( $the_query->have_posts() ) : $the_query->the_post();
// post stuff here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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