ความช่วยเหลือ SQL กับการสืบค้น MAX

ฉันมีตารางประเทศชื่อ BBC (ชื่อ, ภูมิภาค, พื้นที่, ประชากร, GDP)

ฉันต้องการตารางที่มีภูมิภาค ชื่อ และประชากรของประเทศที่ใหญ่ที่สุด (มีประชากรมากที่สุด) ตามภูมิภาค จนถึงตอนนี้ฉันได้ลองสิ่งนี้แล้ว:

SELECT region, name, MAX(population)
FROM bbc
GROUP BY region

มันทำให้ฉันมีข้อความแสดงข้อผิดพลาด: ORA-00979: Not a GROUP BY Expression

ฉันพยายามเปลี่ยนเป็น GROUP BY ภูมิภาค ชื่อ แต่ไม่ได้ให้ตารางที่ถูกต้องแก่ฉัน


person tiagovrtr    schedule 09.07.2011    source แหล่งที่มา
comment
เกิดอะไรขึ้นกับ MAX(population) ที่ 2? คุณเคยเห็นมันทำที่ไหน?   -  person mechanical_meat    schedule 09.07.2011
comment
โอเค แต่อย่าให้มันเกิดขึ้นอีก :p   -  person mechanical_meat    schedule 10.07.2011


คำตอบ (3)


นี่เป็นวิธีที่ง่ายและสั้นที่สุดในการดำเนินการ เนื่องจาก Oracle มีการทดสอบทูเพิล จึงทำให้โค้ดสั้นลงได้:

ขั้นแรก ให้หาจำนวนประชากรสูงสุดในแต่ละภูมิภาค:

SELECT region, MAX(population)
FROM bbc
GROUP BY region

จากนั้นทดสอบประเทศต่างๆ กับมัน:

select region, name, population 
from bbc 
where (region, population) in
      (SELECT region, MAX(population)
       FROM bbc
       GROUP BY region)
order by region

หากคุณต้องการสนับสนุน RDBMS จำนวนมาก ให้ใช้ EXISTS:

select region, name, population 
from bbc o
where exists
      (SELECT null -- neutral. doesn't invoke Cargo Cult Programming ;-)
       FROM bbc
       WHERE region = o.region 
       GROUP BY region
       HAVING o.population = MAX(population) )
order by region

ทดสอบข้อความค้นหาที่นี่ ทั้งคู่มีผลลัพธ์ที่คล้ายกัน: http://sqlzoo.net/0.htm

http://www.ienablemuch.com/2010/05/why-is-exists-select-1-cargo-cult.html

person Michael Buen    schedule 10.07.2011
comment
การสืบค้นทั้งสองนี้มีค่าใช้จ่ายสูงกว่า (อธิบายแผน) มากกว่าการสืบค้นโดยใช้การวิเคราะห์ ทุกอย่างขึ้นอยู่กับเป้าหมายของคุณ - person DCookie; 10.07.2011
comment
นั่นเป็นการยืนยันโดยชัดเจน ;-) เรากำลังทำอะไรในการวิเคราะห์ล่วงหน้า ฉันอาจเสี่ยงต่อการคาดเดาได้ว่ามีวิธีวิทยาการคอมพิวเตอร์ที่เกี่ยวข้องกับแนวทางนั้นมากกว่าการวิเคราะห์ ฟังก์ชันนั้นมีมานานแล้วก่อนที่ CTE/Windowing/Analytics เหล่านั้นจะมาถึงที่เกิดเหตุ ในการใช้งาน C/C++ อย่างชาญฉลาด การวิเคราะห์มี ifs มากมายอยู่ภายใน สามารถรองรับฟังก์ชันการทำงานได้มากมาย ดังนั้นจึงอาจทำงานช้าลงหรือไม่ อาจจะ. แค่ 2 เซ็นต์ของฉัน คำตอบคือไปที่โปรไฟล์ - person Michael Buen; 10.07.2011
comment
ไม่มีข้อพิสูจน์ใดเลย - เพียงแค่สังเกตสิ่งที่เครื่องมือเพิ่มประสิทธิภาพคิดว่าแบบสอบถามจะมีค่าใช้จ่ายในการดำเนินการ คุณถูกต้องอย่างแน่นอนว่าการพิสูจน์อยู่ในหน่วยเมตริก - person DCookie; 10.07.2011

คุณสามารถใช้การวิเคราะห์สำหรับการสืบค้นดังนี้:

SELECT name, region, population
  FROM (SELECT region, name, population
             , MAX(population) OVER (PARTITION BY region) maxpop
          FROM bbc)
 WHERE population = maxpop;

มุมมองอินไลน์จะให้ตารางที่ดูเหมือนตารางฐานของคุณ พร้อมด้วยคอลัมน์เพิ่มเติมที่มีจำนวนประชากรสูงสุดสำหรับภูมิภาค การเลือกระดับบนสุดของคุณจะแสดงประเทศ ภูมิภาค และประชากรของประเทศที่ใหญ่ที่สุดในแต่ละภูมิภาค

เพื่ออธิบายด้วยตัวอย่างที่จำกัด:

SELECT * FROM bbc;

REGION          NAME        POPULATION
--------------- -------     ----------
North America   USA         300000000
North America   Canada      100000000
North America   Mexico       50000000
South America   Brazil       50000000
South America   Argentina    40000000
South America   Venezuela    20000000

เพิ่มฟังก์ชันการวิเคราะห์:

SELECT region, NAME, population
     , MAX(population) OVER (PARTITION BY region) maxpop
  FROM bbc;

REGION          NAME                POPULATION      MAXPOP
--------------- -------             ----------      ----------
North America   USA                 300000000       300000000
North America   Canada              100000000       300000000
North America   Mexico               50000000       300000000
South America   Brazil               50000000        50000000
South America   Argentina            40000000        50000000
South America   Venezuela            20000000        50000000

จากนั้นผลิตภัณฑ์สำเร็จรูป:

NAME    REGION             POPULATION
------- ---------------    -----------
USA     North America       300000000
Brazil  South America        50000000

แก้ไขอีกครั้งหนึ่ง คุณสามารถหลีกเลี่ยงการเลือกแบบซ้อนได้ แต่ไม่ใช่แบบสอบถามย่อย:

SELECT NAME, region, population
  FROM bbc
 WHERE (region, population) IN
       (SELECT region, MAX(population)
          FROM bbc
         group by region);
person DCookie    schedule 09.07.2011
comment
สำหรับภูมิภาคที่กำหนด หากทั้งสองประเทศมีประชากรเท่ากัน (ซึ่งฉันคิดว่าไม่น่าเป็นไปได้อย่างยิ่ง แต่ก็คุ้มค่าที่จะถามเสมอ) ข้อความค้นหานี้จะส่งคืนทั้งสอง: นี่คือสิ่งที่ tiagovrtr กำลังรออยู่หรือไม่ - person Bruno Gautier; 10.07.2011
comment
ใครจะรู้? ไม่เป็นไปตามข้อกำหนด! - person DCookie; 10.07.2011
comment
@BrunoGautier แน่นอนว่ามันใช้งานได้ แต่ฉันพยายามไม่ใช้การเลือกแบบซ้อน มันเป็นไปไม่ได้เหรอ? - person tiagovrtr; 10.07.2011
comment
@OMG มีมากกว่าหนึ่งวิธีที่จะทำ ;-) ฉันสงสัยว่ามีประสิทธิภาพแตกต่างกันหรือไม่ .... - person DCookie; 10.07.2011
comment
@tiagovtr ไม่แน่ใจว่าทำไมคุณถึงต้องการหลีกเลี่ยงการเลือกแบบซ้อน แต่การแก้ไขของฉันแสดงวิธีดำเนินการกับแบบสอบถามย่อย - person DCookie; 10.07.2011
comment
@tiagovrtr ทำไมไม่เลือกซ้อนกัน? ฉันคิดว่าการสืบค้นที่มีตัวเลือกแบบซ้อนมักจะอ่านได้ง่ายกว่า เนื่องจากคุณสามารถดูขั้นตอนที่เกี่ยวข้องเพื่อให้ได้ผลลัพธ์สุดท้ายได้ง่ายขึ้น โดยเฉพาะอย่างยิ่งเมื่อใช้การวิเคราะห์ และฉันก็พบว่าการเดาแผนการดำเนินการนั้นง่ายกว่าด้วย - person Bruno Gautier; 10.07.2011
comment
@OMG ฉันกำลังคิดที่จะใช้ฟังก์ชัน ‹code›ROW_NUMBER‹/code› ;-) - person Bruno Gautier; 10.07.2011
comment
@DCookie ฉันชอบภาพประกอบของคุณ มันแสดงให้เห็นเหตุผลเบื้องหลังการใช้การวิเคราะห์ได้เป็นอย่างดี - person Bruno Gautier; 10.07.2011

ในแจกันส่วนใหญ่ ข้อผิดพลาด ORA-00979 เกิดขึ้นเนื่องจากคอลัมน์ที่ไม่ได้รวมกลุ่มไม่รวมอยู่ใน GROUP BY clause ในกรณีนี้ คุณต้องรวม ชื่อ ไว้ใน GROUP BY clause ของคุณด้วย นอกจากนี้ คุณไม่ควรเรียกใช้ฟังก์ชัน MAX ในคำสั่ง FROM ของคุณ

SELECT region, name, MAX(population)
FROM bbc
GROUP BY region, name
person THE DOCTOR    schedule 09.07.2011