ORA-00979 không phải là một nhóm theo biểu thức


147

Tôi đang nhận ORA-00979 với truy vấn sau:

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;

Tôi không thể tìm thấy bất kỳ ví dụ nào có cả mệnh đề GROUP BY và ORDER BY trong cùng một truy vấn. Tôi đã cố gắng loại bỏ từng trường khỏi nhóm một lần, nhưng vẫn nhận được cùng một lỗi.

Câu trả lời:


232

Bạn phải đặt tất cả các cột của SELECTtrong GROUP BYhoặc sử dụng các chức năng trên chúng mà nén kết quả cho một giá trị duy nhất (như MIN, MAXhoặc SUM).

Một ví dụ đơn giản để hiểu tại sao điều này xảy ra: Hãy tưởng tượng bạn có một cơ sở dữ liệu như thế này:

FOO BAR
0   A
0   B

và bạn chạy SELECT * FROM table GROUP BY foo. Điều này có nghĩa là cơ sở dữ liệu phải trả về một hàng duy nhất là kết quả với cột đầu tiên 0để thực hiện GROUP BYnhưng hiện có hai giá trị được barchọn. Kết quả nào bạn mong đợi - Ahoặc B? Hoặc cơ sở dữ liệu nên trả lại nhiều hơn một hàng, vi phạm hợp đồng GROUP BY?


7
Không, bạn không cần phải đặt chúng theo thứ tự theo mệnh đề
Xaisoft

3
Tôi đã thử thêm hai cột trong ĐẶT HÀNG THEO NHÓM THEO. Điều đó đã làm việc. Cảm ơn!
Theresa

1
Hoặc nói cách khác: Nếu bạn có hai cột và nhóm đầu tiên, điều đó có nghĩa là bạn sẽ có một vài giá trị từ cột thứ hai trên mỗi hàng kết quả. Vì chỉ có một hàng kết quả duy nhất nhưng có nhiều giá trị để chọn, nên trả về DB nào? Đầu tiên nó vấp ngã?
Aaron Digulla

6
@AaronDigulla Đó là những gì MySQL làm và thế giới đã không kết thúc: p
Chris Baker

1
Tôi đồng ý một phần. Nhưng giả sử trường hợp sau: có 4 cột: A, B, C và D. Bây giờ tôi đặt (A, B, C) làm khóa tổng hợp. Sau đó, "chọn A, B, max (C), D ... nhóm theo A, B" không mơ hồ, vì với mỗi kết hợp của A, B và C, D đã được xác định. Vẫn tiên tri từ chối làm công việc của mình.
ga

17

Bao gồm trong GROUP BYmệnh đề tất cả các SELECTbiểu thức không phải là đối số chức năng nhóm.


9

Quá tệ, Oracle có những hạn chế như thế này. Chắc chắn, kết quả cho một cột không nằm trong NHÓM THEO sẽ là ngẫu nhiên, nhưng đôi khi bạn muốn điều đó. Silly Oracle, bạn có thể làm điều này trong MySQL / MSSQL.

NHƯNG có một công việc xung quanh cho Oracle:

Trong khi dòng sau không hoạt động

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

Bạn có thể lừa Oracle với một số 0 như sau, để giữ cho cột của bạn trong phạm vi, nhưng không được nhóm theo nó (giả sử đây là các số, nếu không hãy sử dụng 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 đưa ra bảng giả của tôi không được xác định chặt chẽ ở trên và rằng tôi không còn làm việc cho một công ty với 11g, tôi không thể cung cấp một ví dụ tốt hơn, mặc dù đó là vấn đề khi tôi thử nghiệm lần cuối.
Joseph Lust

4
Vì tò mò, ví dụ về thời điểm bạn muốn có một kết quả ngẫu nhiên là gì? Tôi không thể nghĩ ra bất kỳ lý do nào bạn muốn nhóm theo FOO và nhận một hàng ngẫu nhiên cho BAR.
Kyle Bridenstine

4

Nếu bạn nhóm nhờ đó có GROUP BYđiều khoản, bất kỳ biểu hiện trong SELECT, mà không phải là chức năng nhóm (hoặc chức năng tổng hợp hoặc cột tổng hợp) như COUNT, AVG, MIN, MAX, SUMvà vân vân ( Danh sách các chức năng tổng hợp ) nên có mặt trong GROUP BYkhoản.

Ví dụ (cách chính xác) (ở đây employee_idkhông phải là hàm nhóm (cột không tổng hợp), do đó, nó phải xuất hiện GROUP BY. Ngược lại, sum (tiền lương) là một hàm nhóm (cột tổng hợp), do đó không bắt buộc phải xuất hiện trong GROUP BYmệnh đề .

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

Ví dụ (sai cách) (ở đây employee_idkhông phải là chức năng nhóm và nó không xuất hiện trong GROUP BYmệnh đề, điều này sẽ dẫn đến Lỗi ORA-00979.

   SELECT employee_id, sum(salary) 
   FROM employees;

Để sửa, bạn cần thực hiện một trong những thao tác sau:

  • Bao gồm tất cả các biểu thức không tổng hợp được liệt kê trong SELECTmệnh đề trong GROUP BYmệnh đề
  • Xóa hàm nhóm (tổng hợp) khỏi SELECTmệnh đề.

2

Bạn nên làm như sau:

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

Lỗi tương tự cũng xuất hiện khi từ khóa UPPER hoặc LOWER không được sử dụng ở cả hai vị trí trong biểu thức chọn và nhóm theo biểu thức.

Sai lầm :-

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

Đúng :-

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

1

Nhóm theo được sử dụng để tổng hợp một số dữ liệu, tùy thuộc vào hàm tổng hợp và ngoài ra bạn cần đặt cột hoặc cột mà bạn cần nhóm.

ví dụ:

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

Điều này sẽ dẫn đến mức lương tối đa của các phòng ban.

Bây giờ nếu chúng ta bỏ qua d.deptnotừ nhóm theo mệnh đề, nó sẽ cho cùng một lỗi.


1

Ngoài các câu trả lời khác, lỗi này có thể xảy ra nếu có sự không nhất quán trong một thứ tự theo mệnh đề. Ví dụ:

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.