MySQL: Penggunaan fungsi grup tidak valid

104

Saya menggunakan MySQL. Ini skema saya:

Pemasok ( sid: integer , sname: string, address string)

Bagian ( pid: integer , pname: string, color: string)

Katalog ( sid: integer, pid: integer , cost: real)

(kunci utama dicetak tebal)

Saya mencoba menulis kueri untuk memilih semua bagian yang dibuat oleh setidaknya dua pemasok:

-- 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
);

Pertama, apakah saya melakukannya dengan cara yang benar?

Kedua, saya mendapatkan kesalahan ini:

1111 - Penggunaan fungsi grup tidak valid

Apa yang saya lakukan salah?

Nick Heiner
sumber

Jawaban:

173

Anda perlu menggunakan HAVING, bukan WHERE.

Perbedaannya adalah: WHEREklausa memfilter baris yang dipilih MySQL. Kemudian MySQL mengelompokkan baris-baris tersebut dan menggabungkan angka-angka untuk COUNTfungsi Anda .

HAVINGseperti WHERE, hanya itu terjadi setelahnya para COUNTnilai telah dihitung, sehingga akan bekerja seperti yang Anda harapkan. Tulis ulang subkueri Anda sebagai:

(                  -- 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
sumber
25
Juga jika GROUP BY digunakan, HAVING harus setelah GROUP BY
Viacheslav
1
Juga, GROUP BY harus sebelum HAVING .... Seharusnya sudah membaca komentar Bandolero: D
Andrew
8

Pertama, kesalahan yang Anda dapatkan adalah karena tempat Anda menggunakan COUNTfungsi - Anda tidak dapat menggunakan fungsi agregat (atau grup) diWHERE klausa.

Kedua, daripada menggunakan subkueri, cukup gabungkan tabel itu sendiri:

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

Yang saya percaya harus mengembalikan hanya baris di mana setidaknya dua baris ada dengan yang sama pidtetapi setidaknya ada 2 sids. Untuk memastikan Anda mendapatkan kembali hanya satu baris per pidsaya telah menerapkan klausa pengelompokan.

Mark Elliot
sumber
Mungkinkah saya bahkan tidak perlu bergabung? (lihat jawaban saya yang diperbarui, di mana saya memberikan solusi yang memungkinkan.)
Nick Heiner
@Rosarch, saya rasa Anda ingin menggunakan COUNT(DISTINCT sid)kueri yang telah diperbarui.
Mark Elliot
Bukankah sidselalu harus berbeda pula, karena siddan pidbersama - sama membentuk kunci utama untuk Catalog?
Nick Heiner