Filtering WP_Query result by category

The category parameters of WP_Query does not have this type of logic. category__and and category__in does not return posts in child categories of the set categories.

I would suggest that you make use of the tax_query parameters in WP_Query, which have the logic you are looking for. The relation parameter has two possible values, AND and OR

relation (string) – The logical relationship between each inner taxonomy array when there is more than one. Possible values are ‘AND’, ‘OR’. Do not use with a single inner taxonomy array.

Also, by default, child terms are included in a tax_query, and that is what you need.

include_children (boolean) – Whether or not to include children for hierarchical taxonomies. Defaults to true.

You can do something like this:

$args = array(
    'post_type' => 'post',
    'tax_query' => array(
    'relation' => 'AND',
        array(
            'taxonomy' => 'category',
            'field'    => 'term_id',
            'terms'    => 1,
        ),
        array(
            'taxonomy' => 'category',
            'field'    => 'term_id',
            'terms'    => 2,
            'include_children' => false,
        ),
    ),
);
$query = new WP_Query( $args );

What this code does, it looks for posts that are in category 1 and in its child categories, also, it checks whether these posts from category 1 and its child categories are also in category 2. The list of posts returned will be posts that are in category 1 or any of its child categories and which is also in category 2.

I have excluded the child categories from category 2, but you can remove this if needed.