Tecnicamente, sua consulta pode funcionar assim (não tenho certeza sobre o objetivo desta consulta):
SELECT 9 AS keyword_id, count(DISTINCT m.id) AS total, t.parent_id AS tag_id
FROM (
SELECT unnest(m.taglist) AS tag_id
FROM mentions m
WHERE m.search_id = 3
AND 9 = ANY (m.taglist)
) m
JOIN tags t USING (tag_id) -- assumes tag.tag_id!
GROUP BY t.parent_id;
No entanto, parece-me que você está indo na direção errada aqui. Normalmente, seria removido o array redundante
taglist
e mantenha o esquema de banco de dados normalizado. Então sua consulta original deve servir bem, apenas encurtando a sintaxe com aliases:SELECT 9 AS keyword_id, count(DISTINCT m.id) AS total, t.parent_id AS tag_id
FROM mentions m
JOIN taggings mt ON mt.mention_id = m.id
JOIN tags t ON t.id = mt.tag_id
WHERE 9 = ANY (m.taglist)
AND m.search_id = 3
GROUP BY t.parent_id;
Desvendar o mistério
<rant>
A causa raiz para seus "resultados diferentes" é a infeliz convenção de nomenclatura que alguns ORMs intelectualmente desafiados impor às pessoas.Estou falando de
id
como nome da coluna. Nunca use esse antipadrão em um banco de dados com mais de uma tabela. Certo, isso significa basicamente qualquer base de dados. Assim que você se juntar a um monte de tabelas (é isso que você faz em um banco de dados) você acaba com um monte de colunas chamadas id
. Totalmente inútil.A coluna ID de uma tabela chamada
tag
deve ser tag_id
(a menos que haja outro nome descritivo). Nunca id
.</rant>
Sua consulta conta inadvertidamente
tags
em vez de mentions
:SELECT 25 AS keyword_id, count(m.id) AS total, t.parent_id AS tag_id
FROM (
SELECT unnest(m.taglist) AS id
FROM mentions m
WHERE m.search_id = 4
AND 25 = ANY (m.taglist)
) m
JOIN tags t USING (id)
GROUP BY t.parent_id;
Deve funcionar desta forma:
SELECT 25 AS keyword_id, count(DISTINCT m.id) AS total, t.parent_id
FROM (
SELECT m.id, unnest(m.taglist) AS tag_id
FROM mentions m
WHERE m.search_id = 4
AND 25 = ANY (m.taglist)
) m
JOIN tags t ON t.id = m.tag_id
GROUP BY t.parent_id;
Eu também adicionei de volta o
DISTINCT
para o seu count()
que se perdeu ao longo do caminho em sua consulta.