ORA-00979 bukan grup dengan ekspresi


147

Saya mendapatkan ORA-00979 dengan pertanyaan berikut:

SELECT cr.review_sk, cr.cs_sk, cr.full_name,
tolist(to_char(cf.fact_date, 'mm/dd/yyyy')) "appt",
cs.cs_id, cr.tracking_number
from review cr, cs, fact cf
where cr.cs_sk = cs.cs_sk
and UPPER(cs.cs_id) like '%' || UPPER(i_cs_id) || '%'
and row_delete_date_time is null
and cr.review_sk = cf.review_wk (+)
and cr.fact_type_code (+) = 183050
GROUP BY cr.review_sk, cr.cs_sk, cf.fact_date, cr.tracking_number
ORDER BY cs.cs_id, cr.full_name;

Saya tidak dapat menemukan contoh yang memiliki klausa GROUP BY dan ORDER BY dalam kueri yang sama. Saya mencoba menghapus setiap bidang dari grup satu per satu, tetapi saya masih mendapatkan kesalahan yang sama.

Jawaban:


232

Anda harus meletakkan semua kolom SELECTdi dalam GROUP BYatau menggunakan fungsi yang mengkompres hasil ke nilai tunggal (seperti MIN, MAXatau SUM).

Contoh sederhana untuk memahami mengapa ini terjadi: Bayangkan Anda memiliki database seperti ini:

FOO BAR
0   A
0   B

dan kamu lari SELECT * FROM table GROUP BY foo. Ini berarti database harus mengembalikan satu baris sebagai hasil dengan kolom pertama 0untuk memenuhi GROUP BYtetapi sekarang ada dua nilai baruntuk dipilih. Hasil mana yang Anda harapkan - Aatau B? Atau haruskah database mengembalikan lebih dari satu baris, melanggar kontrak GROUP BY?


7
Tidak, Anda tidak perlu memasukkannya dalam klausa Anda
Xaisoft

3
Saya mencoba menambahkan dua kolom di ORDER BY ke GROUP BY. Itu berhasil. Terima kasih!
Theresa

1
Atau dengan kata lain: Jika Anda memiliki dua kolom dan grup dengan yang pertama, itu berarti Anda akan memiliki beberapa nilai dari kolom kedua per baris hasil. Karena hanya ada satu baris hasil tetapi banyak nilai untuk dipilih, yang mana yang harus dikembalikan oleh DB? Yang pertama ditemukan?
Aaron Digulla

6
@ AaronDigulla Itulah yang dilakukan MySQL, dan dunia tidak berakhir: p
Chris Baker

1
Saya sebagian setuju. Tetapi asumsikan kasus berikut: ada 4 kolom: A, B, C dan D. Sekarang saya menetapkan (A, B, C) sebagai kunci komposit. Kemudian "pilih A, B, maks (C), D ... kelompok dengan A, B" tidak ambigu, karena untuk setiap kombinasi A, B dan C, D sudah ditentukan. Masih oracle menolak untuk melakukan tugasnya.
ga

17

Sertakan dalam GROUP BYklausa semua SELECTekspresi yang bukan argumen fungsi grup.


9

Sayang sekali Oracle memiliki keterbatasan seperti ini. Tentu, hasil untuk kolom yang tidak ada dalam GROUP BY akan acak, tetapi terkadang Anda menginginkannya. Oracle konyol, Anda dapat melakukan ini di MySQL / MSSQL.

TAPI ada pekerjaan untuk Oracle:

Sementara baris berikut tidak berfungsi

SELECT unique_id_col, COUNT(1) AS cnt FROM yourTable GROUP BY col_A;

Anda dapat menipu Oracle dengan beberapa 0 seperti berikut ini, untuk menjaga ruang lingkup kolom Anda, tetapi tidak mengelompokkannya (dengan asumsi ini adalah angka, jika tidak gunakan CONCAT)

SELECT MAX(unique_id_col) AS unique_id_col, COUNT(1) AS cnt 
FROM yourTable GROUP BY col_A, (unique_id_col*0 + col_A);

@ GlennFromIowa mengingat tabel semu saya tidak didefinisikan secara ketat di atas, dan bahwa saya tidak lagi bekerja untuk perusahaan dengan 11g, saya tidak bisa memberikan contoh yang lebih baik, meskipun itu masalah ketika saya terakhir mengujinya.
Joseph Lust

4
Hanya ingin tahu apa contoh kapan Anda ingin hasil acak? Saya tidak dapat memikirkan alasan apa pun yang Anda inginkan untuk dikelompokkan berdasarkan FOO dan mendapatkan baris acak untuk BAR.
Kyle Bridenstine

4

Jika Anda pengelompokan berdasarkan termasuk GROUP BYklausul, setiap ekspresi di SELECT, yang tidak fungsi kelompok (atau fungsi agregat atau kolom dikumpulkan) seperti COUNT, AVG, MIN, MAX, SUMdan sebagainya ( Daftar fungsi Agregat ) harus hadir dalam GROUP BYklausa.

Contoh (cara yang benar) (di sini employee_idbukan fungsi grup (kolom non-agregat), jadi harus muncul masuk GROUP BY. Sebaliknya, jumlah (gaji) adalah fungsi grup (kolom agregat), sehingga tidak perlu muncul di GROUP BYklausa .

   SELECT employee_id, sum(salary) 
   FROM employees
   GROUP BY employee_id; 

Contoh (cara yang salah) (di sini employee_idbukan fungsi grup dan tidak muncul dalam GROUP BYklausa, yang akan mengarah ke Kesalahan ORA-00979.

   SELECT employee_id, sum(salary) 
   FROM employees;

Untuk memperbaiki Anda perlu melakukan salah satu dari yang berikut:

  • Sertakan semua ekspresi non-agregat yang tercantum dalam SELECTklausa dalam GROUP BYklausa
  • Hapus fungsi grup (agregat) dari SELECTklausa.

2

Anda harus melakukan hal berikut:

SELECT cr.review_sk, 
       cr.cs_sk, 
       cr.full_name,
       tolist(to_char(cf.fact_date, 'mm/dd/yyyy')) "appt",
       cs.cs_id, 
       cr.tracking_number
from review cr, cs, fact cf
where cr.cs_sk = cs.cs_sk
       and UPPER(cs.cs_id) like '%' || UPPER(i_cs_id) || '%'
       and row_delete_date_time is null
       and cr.review_sk = cf.review_wk (+)
       and cr.fact_type_code (+) = 183050
GROUP BY cr.review_sk, cr.cs_sk, cf.fact_date, cr.tracking_number, cs.cs_id, cr.full_name
ORDER BY cs.cs_id, cr.full_name;

1

Kesalahan yang sama juga terjadi ketika kata kunci UPPER atau RENDAH tidak digunakan di kedua tempat dalam ekspresi pilih dan grup menurut ekspresi.

Salah: -

select a , count(*) from my_table group by UPPER(a) .

Baik :-

select UPPER(a) , count(*) from my_table group by UPPER(a) .

1

Grup oleh digunakan untuk mengumpulkan beberapa data, tergantung pada fungsi agregat, dan selain itu Anda perlu meletakkan kolom atau kolom yang Anda butuhkan untuk pengelompokan.

sebagai contoh:

select d.deptno, max(e.sal) 
from emp e, dept d
where e.deptno = d.deptno
group by d.deptno;

Ini akan menghasilkan gaji maksimum departemen.

Sekarang jika kita menghilangkan d.deptnogrup dari dengan klausa itu akan memberikan kesalahan yang sama.


1

Selain jawaban lain, kesalahan ini dapat terjadi jika ada ketidakkonsistenan dalam urutan dengan klausa. Misalnya:

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.