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.
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?
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 NULL
s. c'est-à-dire lorsque NULL
retourne 0
.
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 ....
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.
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.
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;
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.
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
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;)
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_;