web-dev-qa-db-fra.com

Requête avec LEFT JOIN ne renvoyant pas de lignes pour un nombre de 0

J'essaie d'obtenir ce qui suit pour retourner un nombre pour chaque organisation utilisant une jointure gauche dans PostgreSQL, mais je ne peux pas comprendre pourquoi cela ne fonctionne pas:

  select o.name as organisation_name,
         coalesce(COUNT(exam_items.id)) as total_used
  from organisations o
  left join exam_items e on o.id = e.organisation_id
  where e.item_template_id = #{sanitize(item_template_id)}
  and e.used = true
  group by o.name
  order by o.name

L'utilisation de coalesce ne semble pas fonctionner. Je suis à bout de souffle! Toute aide serait certainement appréciée!

Pour clarifier ce qui ne fonctionne pas, pour le moment, la requête ne renvoie que des valeurs pour les organisations dont le nombre est supérieur à 0. J'aimerais qu'il renvoie une ligne pour chaque organisation, quel que soit le nombre.

Définitions des tableaux:

TABLE exam_items
  id serial NOT NULL
  exam_id integer
  item_version_id integer
  used boolean DEFAULT false
  question_identifier character varying(255)
  organisation_id integer
  created_at timestamp without time zone NOT NULL
  updated_at timestamp without time zone NOT NULL
  item_template_id integer
  stem_id integer
  CONSTRAINT exam_items_pkey PRIMARY KEY (id)

TABLE organisations
  id serial NOT NULL
  slug character varying(255)
  name character varying(255)
  code character varying(255)
  address text
  organisation_type integer
  created_at timestamp without time zone NOT NULL
  updated_at timestamp without time zone NOT NULL
  super boolean DEFAULT false
  CONSTRAINT organisations_pkey PRIMARY KEY (id)
31
mulus

Cela devrait fonctionner:

SELECT o.name AS organisation_name
     , COUNT(e.id) AS total_used
FROM   organisations   o
LEFT   JOIN exam_items e ON e.organisation_id = o.id 
                        AND e.item_template_id = #{sanitize(item_template_id)}
                        AND e.used = true
GROUP  BY o.name
ORDER  BY o.name;
  • Vous aviez un LEFT [OUTER] JOIN Mais les dernières conditions WHERE l'ont fait agir comme un simple [INNER] JOIN.
    Déplacez la ou les conditions dans la clause JOIN pour la faire fonctionner comme prévu. De cette façon, seules les lignes qui remplissent toutes ces conditions sont jointes en premier lieu (ou les colonnes de la table à droite sont remplies de NULL). Comme vous l'avez fait, les lignes jointes sont testées pour des conditions supplémentaires virtuellement après le LEFT JOIN Et supprimées si elles ne passent pas, tout comme avec un simple JOIN .

  • COUNT() ne renvoie jamais NULL pour commencer. C'est une exception parmi les fonctions agrégées à cet égard. Donc, COALESCE(COUNT(col))  jamais est logique, même avec des paramètres supplémentaires. Le manuel :

    Il convient de noter que à l'exception de count, ces fonctions renvoient une valeur nulle lorsqu'aucune ligne n'est sélectionnée.

Accentuation mienne.

61
Erwin Brandstetter

Pour être clair,

la ligne importante est GROUP BY MAIN_TABLE qui gérera la valeur NULL de SOME_TABLE

SELECT COUNT(ST.ID)
FROM MAIN_TABLE MT
LEFT JOIN SOME_TABLE ST ON MT.ID = ST.MT_ID

GROUP BY MT.ID
9
Sruit A.Suk