MySQL: недопустимое использование групповой функции

105

Я использую MySQL. Вот моя схема:

Поставщики ( sid: целое число , sname: строка, адресная строка)

Части ( pid: целое число , pname: строка, цвет: строка)

Каталог ( sid: integer, pid: integer , cost: real)

(первичные ключи выделены жирным шрифтом)

Я пытаюсь написать запрос, чтобы выбрать все детали, изготовленные как минимум двумя поставщиками:

-- Find the pids of parts supplied by at least two different suppliers.
SELECT c1.pid                      -- select the pid
FROM Catalog AS c1                 -- from the Catalog table
WHERE c1.pid IN (                  -- where that pid is in the set:
    SELECT c2.pid                  -- of pids
    FROM Catalog AS c2             -- from catalog
    WHERE c2.pid = c1.pid AND COUNT(c2.sid) >= 2 -- where there are at least two corresponding sids
);

Во-первых, правильно ли я поступаю?

Во-вторых, я получаю такую ​​ошибку:

1111 - Недопустимое использование групповой функции

Что я делаю не так?

Ник Хайнер
источник

Ответы:

176

Тебе нужно использовать HAVING, а не WHERE.

Разница в том, что WHEREпредложение фильтрует, какие строки выбирает MySQL. Затем MySQL группирует строки вместе и объединяет числа для вашей COUNTфункции.

HAVINGэто как WHEREтолько это происходит послеCOUNT того, как значение было вычислено, поэтому он будет работать , как вы ожидаете. Перепишите свой подзапрос как:

(                  -- where that pid is in the set:
SELECT c2.pid                  -- of pids
FROM Catalog AS c2             -- from catalog
WHERE c2.pid = c1.pid
HAVING COUNT(c2.sid) >= 2)
RJH
источник
25
Также, если используется GROUP BY, HAVING должен быть после GROUP BY
Вячеслав
1
Кроме того, GROUP BY должна быть перед HAVING .... Должен был прочитать комментарий Бандолеро: D
Эндрю
9

Во-первых, ошибка, которую вы получаете, связана с тем, где вы используете COUNTфункцию - вы не можете использовать агрегатную (или групповую) функцию в WHEREпредложении.

Во-вторых, вместо использования подзапроса просто присоедините таблицу к самой себе:

SELECT a.pid 
FROM Catalog as a LEFT JOIN Catalog as b USING( pid )
WHERE a.sid != b.sid
GROUP BY a.pid

Который, я считаю, должен возвращать только строки, в которых существует не менее двух строк с одинаковыми, pidно есть не менее 2 sidс. Чтобы убедиться, что вы вернетесь только к одной строке, pidя применил предложение группировки.

Марк Эллиот
источник
Возможно ли, что мне даже не нужно соединение? (см. мой обновленный ответ, где я предложил возможное решение.)
Ник Хайнер,
@Rosarch, я думаю, вы захотите использовать COUNT(DISTINCT sid)в своем обновленном запросе.
Марк Эллиот
В sidлюбом случае не всегда нужно было бы отличаться, потому что sidи pidвместе образуют первичный ключ для Catalog?
Ник Хайнер,