Pense no que seu código está fazendo logicamente:
( 1 IN (tag.tag_id) ) AND ( 2 IN (tag.tag_id) )
é equivalente a
( 1 = (tag.tag_id) ) AND (2 = (tag.tag_id) )
Não tem como
tag.tag_id
pode satisfazer ambas as condições ao mesmo tempo, então o AND nunca é verdadeiro. Parece que a versão OR que você citou em sua pergunta é a que você realmente deseja:
SELECT DISTINCT name FROM person LEFT JOIN tag ON person.id = tag.person_id
WHERE ( ( 1 IN (tag.tag_id) ) OR ( 2 IN (tag.tag_id) ) );
Usando a cláusula IN mais apropriadamente, você poderia escrever isso como:
SELECT DISTINCT name FROM person LEFT JOIN tag ON person.id = tag.person_id
WHERE tag.tag_id in (1,2);
Uma observação final, porque você está referenciando uma coluna da tabela LEFT JOINed em sua cláusula WHERE (
tag.tag_id
), você está realmente forçando isso a se comportar como um INNER JOIN. Para realmente obter um LEFT JOIN, você precisaria remover os critérios de WHERE e torná-los parte das condições de JOIN:SELECT DISTINCT name FROM person LEFT JOIN tag ON person.id = tag.person_id
AND tag.tag_id in (1,2);