Получить значение 0 из числа без строк - PullRequest
17 голосов
/ 01 февраля 2011

У меня есть 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, если кандидат не имеет приложений или не существует.

EDIT

У меня сейчас:

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

Работает отлично. Но можно ли написать это проще или это лучшее решение? Должен ли я создать какие-либо индексы?

Ответы [ 6 ]

15 голосов
/ 01 февраля 2011

Вам необходимо использовать функцию COALESCE в PostgreSQL http://developer.postgresql.org/pgdocs/postgres/functions-conditional.html

По сути, вы должны указать SQL, как обрабатывать NULL с. т.е. когда NULL вернуть 0.

5 голосов
/ 01 февраля 2011

Вы не можете.

Если у вашего кандидата нет приложений, то у вас нет возможности прочитать их candidate_id значение

Откуда вы знаете, что кандидат существует, если его нет в таблице Applications?

В вашем примере кода, нет кандидата , и поэтому вы не могли бы сказать, что у конкретного кандидата было ноль заявок. По этой логике существует бесконечное число кандидатов с нулевым числом заявок.

Вам понадобится таблица кандидатов для получения этой информации ... если вы не предполагаете, что кандидат существует, потому что вы запрашиваете его по идентификатору?

EDIT

Теперь, когда у вас есть таблица Candidates, вы можете сделать это:

SELECT c.ID, (SELECT COUNT(a.*) FROM Applications a WHERE a.candidate_id = c.ID) 
FROM Candidate c
WHERE ....
2 голосов
/ 01 февраля 2011

Возможно:

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

1 голос
/ 12 декабря 2012

Я был осведомлен об этом вопросе от автора этого связанного , который был убежден, что его проблема не может быть решена после прочтения здесь.Ну, это возможно.

Этому ответу почти два года, но последние вопросы еще не получены.

Запрос

Возможно линапишите проще или это лучшее решение?

Чтобы проверить одиночный идентификатор , найденный вами запрос хорош.Вы можете упростить:

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, вам, скорее всего, нужно, чтобы это началосьс.

1 голос
/ 01 февраля 2011

Вы можете попробовать что-то вроде следующего (при условии, что у вас есть таблица-кандидат и мои предположения о правильности имен таблиц / столбцов).

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 голос
/ 01 февраля 2011

Разве вы не можете использовать это утверждение:

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

Оно должно возвращать count (), и вам не нужно подзапрос.

РЕДАКТИРОВАТЬ: Мэтью PK правильно и Энди Патон имеетлучше ответ;)

...