web-dev-qa-db-fra.com

Obtenez 0 valeur à partir d'un nombre sans lignes

J'ai SELECT:

SELECT c FROM (
    SELECT "candidate_id" as id, count("candidate_id") as c
    FROM "Applicaions"
    GROUP BY "candidate_id"
) as s WHERE id= _SOME_ID_;

Mais cela ne renvoie une valeur que si count > 0. Si count = 0 il ne renvoie rien. Comment puis-je avoir 0 pour un "Candidat" qui n'a pas de candidature?

Il y a le tableau "Candidats".
J'ai besoin d'obtenir 0 si le candidat n'a aucune candidature ou n'existe pas.

ÉDITER

J'ai maintenant:

SELECT COALESCE ((SELECT count("candidate_id") as c
FROM "Applicaions" WHERE "candidate_id"=_SOME_ID_
GROUP BY "candidate_id"), 0);

Cela fonctionne parfaitement. Mais est-il possible de l'écrire plus simplement ou est-ce la meilleure solution? Dois-je créer des index?

21
Miko Kronn

Vous devez utiliser la fonction COALESCE dans PostgreSQL http://developer.postgresql.org/pgdocs/postgres/functions-conditional.html

Essentiellement, vous devez indiquer à SQL comment gérer NULLs. c'est-à-dire lorsque NULL retourne 0.

16
diagonalbatman

Tu ne peux pas.

Si votre candidat n'a aucune candidature, vous n'avez aucun moyen de lire leur candidate_id valeur

Comment sauriez-vous qu'un candidat existe sans qu'il soit dans la table Applications?

Dans votre exemple de code, il n'y a pas de candidat et donc vous ne pouviez pas dire qu'un candidat spécifique n'avait aucune candidature. Selon cette logique, il existe un nombre infini de candidats n'ayant aucune candidature.

Vous aurez besoin d'un tableau des candidats pour obtenir ces informations ... à moins que votre intention soit de présumer qu'un candidat existe parce que vous le demandez par pièce d'identité?

MODIFIER

Maintenant que vous avez une table Candidates, vous pouvez faire ceci:

SELECT c.ID, (SELECT COUNT(a.*) FROM Applications a WHERE a.candidate_id = c.ID) 
FROM Candidate c
WHERE ....
5
Matthew

J'ai été informé de cette question par l'auteur de celui-ci qui a été amené à croire que son problème ne pouvait pas être résolu après avoir lu ici. Eh bien, c'est possible.

Cette réponse a presque deux ans, mais les dernières questions étaient toujours en suspens.

Requete

Est-il possible de l'écrire plus simplement ou est-ce la meilleure solution?

Pour tester un ID unique , la requête que vous avez trouvée est bonne. Vous pouvez simplifier:

SELECT coalesce((SELECT count(candidate_id)
FROM   "Applications" WHERE candidate_id = _SOME_ID_), 0) AS c;
  • La condition WHERE se limite à un seul candidate_id Et il y a une seule fonction d'agrégation dans la liste SELECT. GROUP BY candidate_id Était redondant.

  • L'alias de colonne a été avalé par COALESCE(). Si vous souhaitez nommer la colonne résultante, déplacez l'alias jusqu'à la fin.

  • Vous n'avez pas besoin de guillemets doubles pour un identifiant normal en minuscules.

Une autre forme, plus propre (à mon humble avis) serait d'utiliser LEFT JOIN:

SELECT count(a.candidate_id) AS c
FROM  (SELECT _SOME_ID_ AS candidate_id) x
LEFT   JOIN "Applicaions" a USING (candidate_id)

Cela fonctionne bien pour plusieurs ID , aussi:

WITH x(candidate_id) AS (
   VALUES
     (123::bigint)
    ,(345)
    ,(789)
   )
SELECT x.candidate_id, count(a.candidate_id) AS c
FROM   x
LEFT   JOIN "Applicaions" a USING (candidate_id)
GROUP  BY x.candidate_id;
  • LEFT JOIN Est généralement plus rapide pour une longue liste que plusieurs clauses WHERE ou une expression IN.

Ou, pour toutes les lignes de votre tableau "Candidats":

SELECT x.candidate_id, count(a.candidate_id) AS c
FROM   "Candidates" x
LEFT   JOIN "Applications" a USING (candidate_id)
GROUP  BY x.candidate_id;

Index

Dois-je créer des index?

Si les performances de lecture sont importantes et que le tableau contient plus que quelques lignes, vous certainement avez besoin d'un index du formulaire:

CREATE INDEX foo_idx ON "Applications" (candidate_id);

Comme cela semble être une colonne de clé étrangère référençant "Candidates".candidate_id, Vous devriez très probablement l'avoir pour commencer.

3
Erwin Brandstetter

Peut-être:

SELECT CASE c WHEN NULL THEN 0 ELSE c END
    FROM (
    SELECT "candidate_id" as id, count("candidate_id") as c
    FROM "Applicaions"
    GROUP BY "candidate_id"
) as s WHERE id= _SOME_ID_;

en supposant que le "rien" est vraiment NULL

2
farfromhome

Ne pouvez-vous pas utiliser cette déclaration:

SELECT count("candidate_id") as c
FROM "Applicaions" WHERE "candidate_id"=_SOME_ID_
GROUP BY "candidate_id"

Il devrait retourner count () et vous n'avez pas besoin de sous-requête.

EDIT: Matthew PK a raison et Andy Paton a une meilleure réponse;)

1
Marek Tuchalski

Vous pouvez essayer quelque chose comme ce qui suit (en supposant que vous avez une table candidate et que mon hypothèse de noms de table/colonne est correcte).

SELECT c FROM (
 SELECT "Candidate"."candidate_id" as id, 
 count("Applications"."candidate_id") as c
 FROM "Candidate" LEFT JOIN "Applications" 
 ON "Applications"."candidate_id"="Candidate"."id"     
GROUP BY "Candidate"."candidate_id" ) as s WHERE id= _SOME_ID_;
1
wllmsaccnt