ORA-00979 ไม่ใช่กลุ่มโดยการแสดงออก


147

ฉันได้รับ ORA-00979 ด้วยแบบสอบถามต่อไปนี้:

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;

ฉันไม่พบตัวอย่างใด ๆ ที่มีทั้งประโยค GROUP BY และ ORDER BY ในแบบสอบถามเดียวกัน ฉันพยายามลบแต่ละฟิลด์จากกลุ่มทีละครั้ง แต่ฉันยังคงได้รับข้อผิดพลาดเดียวกัน

คำตอบ:


232

คุณต้องใส่คอลัมน์ทั้งหมดของSELECTในGROUP BYหรือใช้ฟังก์ชั่นที่พวกเขาซึ่งบีบอัดผลให้ค่าเดียว (เช่นMIN, MAXหรือSUM)

ตัวอย่างง่ายๆที่จะเข้าใจว่าทำไมสิ่งนี้ถึงเกิดขึ้น: ลองนึกภาพคุณมีฐานข้อมูลเช่นนี้:

FOO BAR
0   A
0   B

SELECT * FROM table GROUP BY fooและคุณเรียก ซึ่งหมายความว่าฐานข้อมูลจะต้องส่งคืนแถวเดียวเนื่องจากคอลัมน์แรก0จะเติมเต็มGROUP BYแต่ขณะนี้มีสองค่าbarให้เลือก ซึ่งผลที่คุณจะคาดหวัง - AหรือB? หรือฐานข้อมูลควรส่งคืนมากกว่าหนึ่งแถวละเมิดสัญญาGROUP BYหรือไม่


7
ไม่คุณไม่จำเป็นต้องเรียงลำดับตามคำสั่งของคุณ
Xaisoft

3
ฉันลองเพิ่มสองคอลัมน์ใน ORDER BY ไปยัง GROUP BY ที่ได้ผล ขอบคุณ!
เทเรซ่า

1
หรือใช้วิธีอื่น: หากคุณมีสองคอลัมน์และกลุ่มแรกหมายความว่าคุณมีค่าหลายค่าจากคอลัมน์ที่สองต่อแถวผลลัพธ์ เนื่องจากมีแถวผลลัพธ์เพียงแถวเดียว แต่มีหลายค่าให้เลือก DB ควรเลือกค่าใด ครั้งแรกที่มันสะดุดเมื่อ?
Aaron Digulla

6
@AaronDigulla นั่นคือสิ่งที่ MySQL ทำและโลกก็ไม่ได้จบ: p
Chris Baker

1
ฉันเห็นด้วยบางส่วน แต่สมมติว่ากรณีต่อไปนี้: มี 4 คอลัมน์: A, B, C และ D ตอนนี้ฉันตั้ง (A, B, C) เป็นคีย์ผสม จากนั้น "เลือก A, B, สูงสุด (C), D ... กลุ่มโดย A, B" ไม่ชัดเจนเนื่องจากแต่ละชุดของ A, B และ C, D ได้ถูกกำหนดไว้แล้ว ออราเคิลยังคงปฏิเสธที่จะทำงานของมัน
GA

17

รวมไว้ในGROUP BYclause SELECTนิพจน์ทั้งหมดที่ไม่ใช่อาร์กิวเมนต์กลุ่มฟังก์ชัน


9

แย่เกินไป Oracle มีข้อ จำกัด เช่นนี้ แน่นอนว่าผลลัพธ์ของคอลัมน์ที่ไม่อยู่ในกลุ่มตามจะสุ่ม แต่บางครั้งคุณต้องการ Silly Oracle คุณสามารถทำได้ใน MySQL / MSSQL

แต่มีการแก้ไขสำหรับ Oracle:

ในขณะที่บรรทัดต่อไปนี้ใช้งานไม่ได้

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

คุณสามารถหลอกลวง Oracle ด้วย 0 ต่อไปนี้เพื่อรักษาคอลัมน์ของคุณให้อยู่ในขอบเขต แต่ไม่รวมกลุ่มไว้ (สมมติว่าเป็นตัวเลขหรือใช้ 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 เนื่องจากตารางหลอกของฉันไม่ได้กำหนดไว้อย่างเข้มงวดและฉันไม่ได้ทำงานให้กับ บริษัท ที่มี 11g อีกต่อไปฉันไม่สามารถให้ตัวอย่างที่ดีกว่าได้แม้ว่ามันจะเป็นปัญหาเมื่อฉันทดสอบครั้งสุดท้าย
Joseph Lust

4
แค่อยากรู้อยากเห็นตัวอย่างเมื่อคุณต้องการผลการสุ่มคืออะไร? ฉันไม่สามารถคิดเหตุผลใด ๆ ที่คุณต้องการจัดกลุ่มโดย FOO และรับแถวสุ่มสำหรับ BAR
Kyle Bridenstine

4

หากคุณจัดกลุ่มโดยอาศัยอำนาจตามรวมทั้งGROUP BYข้อแสดงออกใด ๆ ในSELECTซึ่งไม่ได้เป็นฟังก์ชั่นกลุ่ม (หรือฟังก์ชันการรวมหรือคอลัมน์รวม) เช่นCOUNT, AVG, MIN, MAX, SUMและอื่น ๆ ( รายการของฟังก์ชั่นรวม ) ควรจะอยู่ในGROUP BYประโยค

ตัวอย่าง (วิธีที่ถูกต้อง) (นี่employee_idไม่ใช่ฟังก์ชั่นกลุ่ม (คอลัมน์ที่ไม่รวมตัวกัน) ดังนั้นมันจะต้องปรากฏขึ้นในGROUP BYทางตรงกันข้าม sum (เงินเดือน) เป็นฟังก์ชั่นกลุ่ม (คอลัมน์รวม) ดังนั้นจึงไม่จำเป็นต้องปรากฏในGROUP BYข้อ .

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

ตัวอย่าง (วิธีที่ผิด) (ที่นี่employee_idไม่ใช่ฟังก์ชั่นกลุ่มและมันไม่ปรากฏในGROUP BYข้อซึ่งจะนำไปสู่ข้อผิดพลาด ORA-00979

   SELECT employee_id, sum(salary) 
   FROM employees;

หากต้องการแก้ไขคุณต้องทำอย่างใดอย่างหนึ่งต่อไปนี้:

  • รวมนิพจน์ที่ไม่ได้รวบรวมไว้ทั้งหมดที่อยู่ในSELECTclause ใน GROUP BYclause
  • ลบฟังก์ชั่นกลุ่ม (รวม) จากSELECTข้อ

2

คุณควรทำสิ่งต่อไปนี้:

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

ข้อผิดพลาดเดียวกันยังมาเมื่อตอนปลายหรือLOWER คำหลักที่ไม่ได้ใช้ในสถานที่ที่เลือกทั้งในการแสดงออกและการจัดกลุ่มตามการแสดงออก

ไม่ถูกต้อง :-

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

ขวา: -

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

1

กลุ่มโดยใช้เพื่อรวบรวมข้อมูลบางอย่างขึ้นอยู่กับฟังก์ชันการรวมและอื่น ๆ นอกเหนือจากที่คุณต้องใส่คอลัมน์หรือคอลัมน์ที่คุณต้องการจัดกลุ่ม

ตัวอย่างเช่น:

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

ซึ่งจะส่งผลให้แผนกเงินเดือนสูงสุด

ตอนนี้ถ้าเราเว้นd.deptnoจากกลุ่มโดยข้อมันจะให้ข้อผิดพลาดเดียวกัน


1

นอกเหนือจากคำตอบอื่น ๆ ข้อผิดพลาดนี้อาจส่งผลหากมีความไม่สอดคล้องกันในการสั่งซื้อตามข้อ ตัวอย่างเช่น

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.