PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Utiliser UNNEST avec un JOIN

Techniquement, votre requête pourrait fonctionner comme ceci (pas tout à fait sûr de l'objectif de cette requête) :

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;

Cependant, il me semble que vous allez dans la mauvaise direction ici. Normalement, on supprimerait le tableau redondant taglist et conserver le schéma de base de données normalisé. Ensuite, votre requête d'origine devrait bien servir, seulement raccourcir la syntaxe avec des alias :

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;

Percez le mystère

<rant> La cause première de vos "résultats différents" est la convention de dénomination malheureuse que certains ORM intellectuellement défiés imposer aux gens.
Je parle de id comme nom de colonne. N'utilisez jamais cet anti-modèle dans une base de données avec plus d'une table. D'accord, cela signifie essentiellement tout base de données. Dès que vous rejoignez un groupe de tables (c'est ce que vous faites dans une base de données) vous vous retrouvez avec un tas de colonnes nommées id . Complètement inutile.
La colonne ID d'une table nommée tag devrait être tag_id (sauf s'il existe un autre nom descriptif). Jamais id .</rant>

Votre requête compte par inadvertance les tags au lieu 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;

Cela devrait fonctionner comme suit :

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;

J'ai également rajouté le DISTINCT à votre count() qui s'est perdu en cours de route dans votre requête.