I'm trying to figure out how to query for posts in my hierarchical custom post type, presumably using WP_Query that have child posts. I can get all pages that don't have children by setting 'post_parent' => 0 in my WP_Query args, but that returns all posts that are not children. I need only posts that have child posts.

2 Answers 2


You can use the post_parent__not_in parameter:

$args = array( 
           'post_type'           => 'cpt',
           'post_parent__not_in' => array( 0 ) 
$query = new WP_Query( $args );

to retrieve child posts of type cpt.

The generated SQL will then include this part:

wp_posts.post_parent NOT IN (0)
  • That's very clever!
    – editor
    Nov 9, 2015 at 5:08

As far I have understood your requirement, I guess this is what you need.

I have documented the code, please go thru it.

Idea:   Collecting all the posts child posts by --->'post_parent__not_in' => array( 0 )<--- 
        in wp_query. Then find their parent posts by eliminating duplicates.

    $query_array = array(
            //Change this post type to your Custom-Post-Type.
        'post_type' => 'news',
            //Showing all posts
        'posts_per_page' => -1, 
            //Giving all child posts only
        'post_parent__not_in' => array( 0 ) 

    $the_query = new WP_Query($query_array);
        //Array to collect all parent posts
    $collect_parents = array();
            //if condition is used to eliminate duplicates, generated by same child post of parent.
        if(!in_array($post->post_parent, $collect_parents)){
            //$collect_parents contains all the parent post id's
            $collect_parents[] = $post->post_parent;

        //Printing all the parent posts
    foreach($collect_parents as $parent){
        <!-- Printing parent post title -->
        <h2><a href="<?php echo get_permalink($parent ); ?>"> <?php echo get_the_title($parent); ?></a></h2>
        <!-- Printing parent post content -->
        <p><?php echo get_post_field( 'post_content', $parent); ?></p>
  • Check out the edit I made. It works, thanks to your help. I'd love to avoid using get_post in the first loop, but I can't figure out any way to get post parent ID.
    – JPollock
    Mar 1, 2014 at 19:28
  • I avoided using get_post in the original code I wrote. Can you tell me the problem in the code, I'll be happy to correct it. of course you are free to design your own code but completely editing the code, removes the crux behind idea. An editor rejected your edit because of that reason. If you are satisfied then please accept the answer or we can work out to make it work. Mar 2, 2014 at 4:35
  • 1
    Sorry, I was hoping that editing the answer would show how close you were. My goal was to make your answer correct so I could accept it, instead of posting my own answer and stealing your points. The problem was that the $collect_parents = []; is improper syntax, the variable $post isn't populated and also the first loop creates duplicate entries. I used get_post() to populate $post and array_unique() to eliminate duplicate ids in the $collect_parents array before the second loop.
    – JPollock
    Mar 2, 2014 at 20:18
  • It's working fine here. I have made a small edit in the code and have changed $collect_parents = [] to $collect_parents = array(). As far as the duplicates are concerned they will be eliminated by this if statement if(!in_array($post->post_parent, $collect_parents)). Please check now. Mar 3, 2014 at 5:00

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.