Ответ 1
Вам нужно использовать функцию COALESCE в PostgreSQL http://developer.postgresql.org/pgdocs/postgres/functions-conditional.html
По существу вам нужно сказать SQL, как обращаться с NULL
s. т.е. когда NULL
возвращает 0
.
У меня есть 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_;
Но это возвращает только значение count > 0
. Если count = 0
ничего не возвращает. Как я могу получить 0
для "Кандидата", у которого нет приложения?
Существует таблица "Кандидаты".
Мне нужно получить 0, если у кандидата нет приложений или не существует.
У меня есть:
SELECT COALESCE ((SELECT count("candidate_id") as c
FROM "Applicaions" WHERE "candidate_id"=_SOME_ID_
GROUP BY "candidate_id"), 0);
Он отлично работает. Но возможно ли это проще или это лучшее решение? Должен ли я создавать какие-либо индексы?
Вам нужно использовать функцию COALESCE в PostgreSQL http://developer.postgresql.org/pgdocs/postgres/functions-conditional.html
По существу вам нужно сказать SQL, как обращаться с NULL
s. т.е. когда NULL
возвращает 0
.
Вы не можете.
Если у вашего кандидата нет приложений, то вы не сможете прочитать их значение candidate_id
Как бы вы знали, что кандидат существует, если они не находятся в таблице Applications
?
В вашем примере кода нет кандидата, и поэтому вы не могли сказать, что у конкретного кандидата были нулевые приложения. По этой логике существует бесконечное число кандидатов, имеющих нулевые приложения.
Вам нужна таблица кандидатов, чтобы получить эту информацию... если ваше намерение не предполагать наличие кандидата, потому что вы запрашиваете его по идентификатору?
ИЗМЕНИТЬ
Теперь, когда у вас есть таблица Candidates
, вы можете сделать это:
SELECT c.ID, (SELECT COUNT(a.*) FROM Applications a WHERE a.candidate_id = c.ID)
FROM Candidate c
WHERE ....
Может быть:
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_;
полагая, что "ничего" действительно NULL
Вы не можете использовать это утверждение:
SELECT count("candidate_id") as c
FROM "Applicaions" WHERE "candidate_id"=_SOME_ID_
GROUP BY "candidate_id"
Он должен возвращать count(), и вам не нужен подзапрос.
ИЗМЕНИТЬ: Мэтью П.К. правильно, и Энди Патон лучше ответил;)
Вы можете попробовать что-то вроде следующего (предполагая, что у вас есть таблица-кандидат, и мое предположение о именах таблиц/столбцов верны).
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_;
Мне был задан этот вопрос автором этого связанного человека, который был убежден, что его проблема не может быть решена после прочтения здесь. Ну, это может быть.
Этот ответ почти два года, но последние вопросы все еще ожидали.
Можно ли написать это проще или это лучшее решение?
Чтобы проверить наличие одного идентификатора, запрос, который вы нашли, хорош. Вы можете упростить:
SELECT coalesce((SELECT count(candidate_id)
FROM "Applications" WHERE candidate_id = _SOME_ID_), 0) AS c;
Условие WHERE
ограничивается одним candidate_id
и в списке SELECT
имеется одна агрегатная функция. GROUP BY candidate_id
был избыточным.
Псевдоним столбца был проглочен COALESCE()
. Если вы хотите назвать полученный столбец, переместите псевдоним до конца.
Другая, более чистая (IMHO) форма должна была бы использовать LEFT JOIN
:
SELECT count(a.candidate_id) AS c
FROM (SELECT _SOME_ID_ AS candidate_id) x
LEFT JOIN "Applicaions" a USING (candidate_id)
Это хорошо работает для нескольких идентификаторов:
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
обычно быстрее для длинного списка, чем несколько предложений WHERE
или выражение IN
.Или, для всех строк в таблице "Кандидаты":
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;
Нужно ли создавать какие-либо индексы?
Если производительность чтения важна, и таблица содержит больше, чем просто пару строк, вам определенно нужен индекс формы:
CREATE INDEX foo_idx ON "Applications" (candidate_id);
Так как это, по-видимому, является столбцом внешнего ключа, ссылающимся на "Candidates".candidate_id
, вам, скорее всего, придется это начать.