okay, so I kind of just ditched my original task that I needed this for, but managed to come around to it again. Here’s what I devised:
You cannot use query_posts for this, I don’t know why it has not been included, but it hasn’t so I’m over it. What you need to do is put together a custom query somewhat like this:
SELECT * FROM $wpdb->posts
LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->term_taxonomy.term_id IN ([category term_id],[tag term_id])
AND !EXISTS(
SELECT NULL
FROM $wpdb->term_relationships
LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE $wpdb->term_relationships.object_id = $wpdb->posts.ID
AND $wpdb->term_taxonomy.term_id IN ([excluded tag or cat term_ids])
)
What you’re doing here is querying for ‘terms’ whether they are categories or post tags, based on their id, so you’ll have to go into your DB and find out the ids of tags. I’m sure you could do another join of term_taxonomy and terms to be able to query based on their name but I didn’t really feel like it, plus this query is already obfuscated enough. The hard part here is excluding terms, or querying for the intersect of terms. The way I’m doing it is by running a subquery (AND EXISTS (foo) for intersects and AND !EXISTS bar) for exclusions).
Sorry for this being kind of convoluted, it’s just something I figured out in an unrelated context so I thought I’d post it here for reference. Reply here if you want to pick my brain on the topic, or if I’m an idiot and have gone about this all wrong…