Zastanów się, co logicznie robi Twój kod:
( 1 IN (tag.tag_id) ) AND ( 2 IN (tag.tag_id) )
jest odpowiednikiem
( 1 = (tag.tag_id) ) AND (2 = (tag.tag_id) )
Nie ma mowy, aby tag.tag_id
może spełniać oba warunki jednocześnie, więc AND nigdy nie jest prawdziwe.
Wygląda na to, że wersja OR, którą wymieniłeś w swoim pytaniu, jest tą, której naprawdę potrzebujesz:
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) ) );
Używając klauzuli IN bardziej odpowiednio, możesz napisać to jako:
SELECT DISTINCT name FROM person LEFT JOIN tag ON person.id = tag.person_id
WHERE tag.tag_id in (1,2);
Ostatnia uwaga, ponieważ odwołujesz się do kolumny z tabeli LEFT JOINed w klauzuli WHERE (tag.tag_id
), naprawdę zmuszasz to, aby zachowywało się jak ZŁĄCZENIE WEWNĘTRZNE. Aby naprawdę uzyskać LEFT JOIN, musisz przenieść kryteria z GDZIE i zamiast tego uczynić je częścią warunków JOIN:
SELECT DISTINCT name FROM person LEFT JOIN tag ON person.id = tag.person_id
AND tag.tag_id in (1,2);