WP_Query – using category__and when one of the categories is 0

You could use tax_query to solve this problem.

I assume 4 and 6 are only categories, so you’ll probably need to construct the queries within the $tax_query array rather than declare it, but let us know if that is a problem. Just remember that relation => 'AND' must be included.

$tax_query = array(
    relation => 'AND',
    array(
        'taxonomy'          => 'category',
        'field'             => 'term_id',   // 'term_id' by default, so just here as an example
        'terms'             => $cat,
        'include_children'  => false,       // true by defualt
        'operator'          => 'IN'         // 'IN' by default, so just here as an example
    ),
    array(
        'taxonomy'          => 'category',
        'terms'             => $cat2,
        'include_children'  => false,       // true by defualt
    )
)

Once you’ve set $tax_query up as you require, just add it to the query, along with any other arguments you desire, like so –

'tax_query' => $tax_query

Check out the Class Reference for WP_Query for more details – http://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters


Update

The OP has suggested that $cat may actually contain multiple categories as opposed to just one, so the code below (untested) should allow for this while still using the `tax_query’ parameter of the query.

/** Ensure that '$cat' is cast as an array */
if(!is_array($cat) && !empty($cat))
    $cat = explode(',', $cat);
    
/** Ensure that '$cat2' is cast as an array */
if(!is_array($cat2) && !empty($cat2))
    $cat2 = explode(',', $cat2);
    
/** Create a single array of all categories */  
$cats_array = $cat + $cat2

/** Create the '$tax_query' variable and cast it as an array */
$tax_query = array();

/** Add each category to the 'tax_query' */
if(!empty($cats_array)) : foreach($cats_array as $single_cat) :

        $tax_query[] = array(
            'taxonomy'          => 'category',
            'terms'             => $single_cat,
            'include_children'  => false,       // true by defualt
        )
        
    endforeach;
endif;

/** Check to see if there is more than one category within the 'tax_query' and if so set the relation to 'AND' */
if(count($tax_query) > 1)
    $tax_query['relation'] = 'AND';

The only thing to note here is that you should check if(!empty($tax_query)) before adding it to your query.

You can use this method for custom taxonomies as well.