HAVING предложение в PostgreSQL - PullRequest
7 голосов
/ 31 марта 2011

Я переписываю запросы MySQL к PostgreSQL.У меня есть таблица со статьями и другая таблица с категориями.Мне нужно выбрать все категории, в которых есть хотя бы 1 статья:

SELECT c.*,(
    SELECT COUNT(*) 
    FROM articles a 
    WHERE a."active"=TRUE AND a."category_id"=c."id") "count_articles" 
FROM articles_categories c 
HAVING (
    SELECT COUNT(*) 
    FROM articles a 
    WHERE a."active"=TRUE AND a."category_id"=c."id" ) > 0

Я не знаю почему, но этот запрос вызывает ошибку:

ERROR:  column "c.id" must appear in the GROUP BY clause or be used in an aggregate function at character 8

Ответы [ 2 ]

13 голосов
/ 31 марта 2011

Предложение HAVING немного сложно понять.Я не уверен, как MySQL интерпретирует это.Но документацию Postgres можно найти здесь:

http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-HAVING

По сути, это говорит:

Наличие HAVING превращает запрос в сгруппированный запрос, даже еслинет предложения GROUP BY.Это то же самое, что происходит, когда запрос содержит агрегатные функции, но не содержит предложения GROUP BY.Считается, что все выбранные строки образуют одну группу, а список SELECT и предложение HAVING могут ссылаться только на столбцы таблицы из агрегатных функций.Такой запрос будет выдавать одну строку, если условие HAVING истинно, и ноль строк, если оно не истинно.

То же самое также объясняется в этом посте , в котором показанокак HAVING без GROUP BY неявно подразумевает стандартную "общую сумму" SQL: 1999, то есть предложение GROUP BY ( ) (которое не поддерживается в PostgreSQL)

Поскольку вы, кажется, не хотите одна строка , предложение HAVING может быть не лучшим выбором.

Учитывая ваш фактический запрос и ваши требования, просто переписать все это и JOIN articles_categories до articles:

SELECT DISTINCT c.*
FROM articles_categories c
JOIN articles a 
ON a.active = TRUE 
AND a.category_id = c.id

альтернатива:

SELECT *
FROM articles_categories c
WHERE EXISTS (SELECT 1 
                FROM articles a
               WHERE a.active = TRUE 
                 AND a.category_id = c.id)
0 голосов
/ 31 марта 2011
select * from categories c
where
exists (select 1 from article a where c.id = a.category_id);

должно быть хорошо ... возможно, проще;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...