DISTINCT funziona su tutte le colonne in SELECT, quindi stai SELECTing tutto restituirà ogni riga distinta e non solo i post distinti. Per aggirare questo problema puoi semplicemente SELEZIONARE i dati dalla tabella dei post e poi DISTINTARli, ad es.
SELECT DISTINCT posts.*
Ma hai anche detto che ti sarebbero piaciuti anche i post e le informazioni sui gatti, se possibile. Un modo per farlo e mantenere una riga per post è utilizzare GROUP_CONCAT quindi la tua domanda potrebbe finire in qualcosa del genere.
SELECT
posts.*,
GROUP_CONCAT(cats.id SEPARATOR ',') as catsList,
GROUP_CONCAT(tags.id SEPARATOR ',') as tagsList
FROM posts
INNER JOIN termRelations ON ( posts.id = termRelations.postId )
LEFT JOIN cats ON ( termRelations.termId = cats.id AND termRelations.termTypeId = 1 AND cats.id =5 )
LEFT JOIN tags ON ( termRelations.termId = tags.id AND termRelations.termTypeId = 0 AND
(tags.id =2
OR tags.id =1)
)
GROUP BY posts.id
LIMIT 0 , 30
Ho apportato un paio di altre modifiche alla tua query originale, come cambiare il primo join in un INNER JOIN e aggiungere i filtri gatti/tag alle condizioni JOIN per le tabelle pertinenti.
ps quando dici di avere tabelle separate per gatti e tag per velocizzare la generazione di elenchi, potresti scoprire che una tabella correttamente indicizzata sarebbe altrettanto veloce e semplificherebbe anche il tuo codice.