Wordpress - how to query posts by category and tag?

Edit: See below for proper way to query category and tag intersections.

global $wp_query;
        $args = array(
        'category__and' => 'category', //must use category id for this field
        'tag__in' => 'post_tag', //must use tag id for this field
        'posts_per_page' => -1); //get all posts

$posts = get_posts($args);
        foreach ($posts as $post) :
  //do stuff 
     endforeach;

I think this is bug in WordPress that has been commented on elsewhere, try using the name of the tag rather than the ID then it should work:

$args = array(
    'posts_per_page' => 3,
    'tag' => 'review',
    'cat' => 9,
);
query_posts($args);

Let us know how you get on, not sure what happens with tags with multiple words in the name.


I stumbled into this same issue and resolved it by making a MySQL request .

in short : get_post($args) will return you posts who have the category=MyCategory OR the tag=MyTag.

what you want is to change your OR to AND .

my logic was to go straight with a MySQL Query:

  • Query 1 = Select all the posts who has the category MyCat
  • Query 2 = Select all the posts who has the tag MyTag
  • FinalLY : Select all the posts who are in Query 1 AND Query 2 .

I used wpdb instead of query_post();

A bit of code (returning published posts with category MyCat and tag MyTag ):

    $query_byTag="
            SELECT wp_posts.ID
            FROM wp_posts, wp_term_relationships, wp_terms
            WHERE wp_posts.ID = wp_term_relationships.object_id
            AND wp_terms.term_id = wp_term_relationships.term_taxonomy_id
            AND wp_terms.name = 'MyTag'";

    $query_byCat="
            SELECT wp_posts.ID
            FROM wp_posts, wp_term_relationships, wp_terms
            WHERE wp_posts.ID = wp_term_relationships.object_id
            AND wp_terms.term_id = wp_term_relationships.term_taxonomy_id
            AND wp_terms.name = 'MyCat'";

$query ="
            SELECT      wp_posts.post_title AS title , 
                        wp_posts.post_content AS content,
                        wp_posts.post_date AS blogdate 
            FROM wp_posts
            WHERE wp_posts.post_status = 'publish'
            AND wp_posts.ID IN (".$query_byTag.")
            AND wp_posts.ID IN (".$query_byCat.")
            ORDER BY wp_posts.post_date DESC ";

$result= $wpdb->get_results($query);

This is a dirty way to do it but I hope it helps =)