MySQL: Недійсне використання функції групи


105

Я використовую MySQL. Ось моя схема:

Постачальники ( sid: ціле число , назва: рядок, адресний рядок)

Частини ( pid: ціле число , ім'я: рядок, колір: рядок)

Каталог ( sid: ціле число, pid: ціле число , вартість: реальне)

(первинні клавіші виділені жирним шрифтом)

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

-- 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 - Недійсне використання групової функції

Що я роблю неправильно?

Відповіді:


173

Вам потрібно користуватися 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)

25
Також якщо використовується GROUP BY, HAVING повинен бути після GROUP BY
В'ячеслав

1
Крім того, група GROUP повинна бути перед ВІДОМОЮ .... Треба прочитати коментар Бандолеро: D
Ендрю

8

По-перше, помилка, яку ви отримуєте, пов’язана з тим, де ви використовуєте 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?
Нік Хайнер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.