รับเร็กคอร์ดที่มีค่าสูงสุดสำหรับผลลัพธ์ SQL กลุ่มที่จัดกลุ่มแต่ละกลุ่ม


229

คุณจะได้รับแถวที่มีค่าสูงสุดสำหรับแต่ละชุดที่จัดกลุ่มได้อย่างไร

ฉันเคยเห็นรูปแบบที่ซับซ้อนเกินไปของคำถามนี้และไม่มีคำตอบที่ดีเลย ฉันพยายามรวบรวมตัวอย่างที่ง่ายที่สุดเท่าที่จะทำได้:

จากตารางด้านล่างด้วยคอลัมน์บุคคลกลุ่มและอายุคุณจะได้คนที่เก่าแก่ที่สุดในแต่ละกลุ่มอย่างไร (เน็คไทภายในกลุ่มควรให้ผลลัพธ์ตัวอักษรแรก)

Person | Group | Age
---
Bob  | 1     | 32  
Jill | 1     | 34  
Shawn| 1     | 42  
Jake | 2     | 29  
Paul | 2     | 36  
Laura| 2     | 39  

ชุดผลลัพธ์ที่ต้องการ:

Shawn | 1     | 42    
Laura | 2     | 39  

3
ข้อควรระวัง: คำตอบที่ยอมรับได้ทำงานในปี 2012 เมื่อมันถูกเขียน อย่างไรก็ตามมันใช้งานไม่ได้ด้วยเหตุผลหลายประการตามที่ระบุในความคิดเห็น
Rick James

คำตอบ:


132

มีวิธีง่ายสุดในการทำเช่นนี้ใน mysql:

select * 
from (select * from mytable order by `Group`, age desc, Person) x
group by `Group`

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

คุณหลีกเลี่ยงแบบสอบถามย่อยที่ซับซ้อนที่พยายามค้นหาmax()ฯลฯ และปัญหาการส่งคืนหลายแถวเมื่อมีมากกว่าหนึ่งที่มีค่าสูงสุดเท่ากัน (เหมือนคำตอบอื่น ๆ )

หมายเหตุ:นี่เป็นวิธีการแก้ปัญหาmysql เท่านั้น ฐานข้อมูลอื่น ๆ ทั้งหมดที่ฉันรู้จะโยนข้อผิดพลาดทางไวยากรณ์ของ SQL พร้อมกับข้อความ "คอลัมน์ที่ไม่รวมจะไม่ปรากฏในกลุ่มตามข้อ" หรือคล้ายกัน เนื่องจากวิธีนี้ใช้ลักษณะการทำงานที่ไม่มีเอกสารความระมัดระวังมากขึ้นอาจต้องการรวมการทดสอบเพื่อยืนยันว่ามันยังทำงานอยู่หาก MySQL รุ่นต่อไปในอนาคตเปลี่ยนพฤติกรรมนี้

อัพเดตเวอร์ชั่น 5.7:

ตั้งแต่เวอร์ชัน 5.7 การsql-modeตั้งค่าจะรวมเป็นONLY_FULL_GROUP_BYค่าเริ่มต้นดังนั้นเพื่อให้งานนี้คุณต้องไม่มีตัวเลือกนี้ (แก้ไขไฟล์ตัวเลือกสำหรับเซิร์ฟเวอร์เพื่อลบการตั้งค่านี้)


66
"mysql แค่ส่งคืนแถวแรก" - บางทีนี่อาจเป็นวิธีการทำงาน แต่ไม่รับประกัน เอกสาร says: "เซิร์ฟเวอร์มีอิสระที่จะเลือกค่าใด ๆ จากแต่ละกลุ่มดังนั้นถ้าพวกเขาเป็นเดียวกันค่าที่ได้รับการแต่งตั้งเป็นไม่แน่นอน." . เซิร์ฟเวอร์ไม่ได้เลือกแถว แต่ค่า (ไม่จำเป็นต้องมาจากแถวเดียวกัน) สำหรับแต่ละคอลัมน์หรือนิพจน์ที่ปรากฏในส่วนSELECTคำสั่งและไม่คำนวณโดยใช้ฟังก์ชันการรวม
axiac

16
พฤติกรรมนี้เปลี่ยนไปบนMySQL 5.7.5และโดยปกติแล้วมันจะปฏิเสธการสืบค้นนี้เนื่องจากคอลัมน์ในส่วนSELECTคำสั่งไม่ได้ขึ้นอยู่กับการใช้งานของGROUP BYคอลัมน์ หากมีการกำหนดค่าให้ยอมรับ (`ONLY_FULL_GROUP_BY` ถูกปิดใช้งาน) จะทำงานเหมือนเวอร์ชันก่อนหน้า (เช่นค่าของคอลัมน์เหล่านั้นไม่แน่นอน)
axiac

17
ฉันประหลาดใจที่คำตอบนี้มี upvotes มากมาย มันผิดและมันก็ไม่ดี แบบสอบถามนี้ไม่รับประกันว่าจะทำงาน ข้อมูลในแบบสอบถามย่อยเป็นชุดที่ไม่ได้เรียงลำดับทั้งๆที่มีคำสั่งตาม MySQL อาจสั่งบันทึกและรักษาลำดับนั้นจริงๆ แต่มันก็ไม่ผิดกฎใด ๆ ถ้ามันหยุดทำในเวอร์ชันต่อ ๆ ไป จากนั้นการGROUP BYรวมตัวเป็นหนึ่งระเบียน แต่ฟิลด์ทั้งหมดจะถูกเลือกโดยพลการจากบันทึก มันอาจเป็นไปได้ว่า MySQL ในขณะนี้ก็มักจะหยิบแถวแรก แต่มันอาจจะเช่นเดียวกับดีเลือกแถวอื่น ๆ หรือแม้กระทั่งจากค่าที่แตกต่างกันแถวในรุ่นอนาคต
Thorsten Kettner

9
โอเคเราไม่เห็นด้วยที่นี่ ฉันไม่ได้ใช้คุณสมบัติที่ไม่มีเอกสารซึ่งเพิ่งเกิดขึ้นกับการทำงานในปัจจุบันและใช้การทดสอบบางอย่างที่หวังว่าจะครอบคลุมในเรื่องนี้ คุณรู้ว่าคุณโชคดีที่การใช้งานปัจจุบันทำให้คุณได้รับบันทึกแรกที่สมบูรณ์ซึ่งเอกสารระบุอย่างชัดเจนว่าคุณอาจได้รับค่าที่ไม่แน่นอนแทน แต่คุณยังคงใช้อยู่ การตั้งค่าเซสชันหรือฐานข้อมูลที่เรียบง่ายบางอย่างอาจเปลี่ยนแปลงได้ตลอดเวลา ฉันคิดว่ามันเสี่ยงเกินไป
Thorsten Kettner

3
คำตอบนี้ดูเหมือนผิด ต่อdoc , เซิร์ฟเวอร์เป็นอิสระในการเลือกค่าใด ๆ จากแต่ละกลุ่ม ... นอกจากนี้การเลือกค่าจากแต่ละกลุ่มไม่สามารถได้รับอิทธิพลจากการเพิ่มข้อ ORDER BY การเรียงชุดผลลัพธ์เกิดขึ้นหลังจากเลือกค่าแล้ว ORDER BY จะไม่ส่งผลกระทบต่อค่าใด ๆ ภายในแต่ละกลุ่มที่เซิร์ฟเวอร์เลือก
Tgr

296

ทางออกที่ถูกต้องคือ:

SELECT o.*
FROM `Persons` o                    # 'o' from 'oldest person in group'
  LEFT JOIN `Persons` b             # 'b' from 'bigger age'
      ON o.Group = b.Group AND o.Age < b.Age
WHERE b.Age is NULL                 # bigger age not found

มันทำงานอย่างไร:

มันตรงกับแต่ละแถวจากoแถวทั้งหมดจากbการมีค่าเดียวกันในคอลัมน์และค่าที่ใหญ่กว่าในคอลัมน์Group Ageแถวใด ๆ ที่oไม่มีค่าสูงสุดของกลุ่มในคอลัมน์Ageจะจับคู่แถวตั้งแต่หนึ่งแถวขึ้นbไป

LEFT JOINทำให้มันตรงกับคนที่เก่าแก่ที่สุดในกลุ่ม (รวมทั้งคนที่เป็นคนเดียวในกลุ่มของพวกเขา) กับแถวเต็มรูปแบบของNULLS จากb( 'ไม่มีอายุที่ใหญ่ที่สุดในกลุ่ม)
การใช้INNER JOINทำให้แถวเหล่านี้ไม่ตรงกันและจะถูกละเว้น

WHEREข้อช่วยให้เฉพาะแถวมีในฟิลด์สกัดจากNULL bพวกเขาเป็นบุคคลที่เก่าแก่ที่สุดจากแต่ละกลุ่ม

อ่านเพิ่มเติม

วิธีการแก้ปัญหานี้และอื่น ๆ อีกมากมายได้อธิบายไว้ในหนังสือSQL Antipatterns: หลีกเลี่ยงการผิดพลาดของการเขียนโปรแกรมฐานข้อมูล


43
BTW สิ่งนี้สามารถส่งคืนสองแถวหรือมากกว่านั้นสำหรับกลุ่มเดียวกันหากo.Age = b.Ageเช่นถ้า Paul จากกลุ่ม 2 อยู่ที่ 39 เช่น Laura อย่างไรก็ตามหากเราไม่ต้องการพฤติกรรมดังกล่าวเราสามารถทำได้:ON o.Group = b.Group AND (o.Age < b.Age or (o.Age = b.Age and o.id < b.id))
Todor

8
! เหลือเชื่อ สำหรับบันทึก 20M จะเร็วกว่าอัลกอริทึม "ไร้เดียงสา" 50 เท่า (เข้าร่วมกับแบบสอบถามย่อยที่มี max ())
user2706534

3
ทำงานได้อย่างสมบูรณ์แบบด้วยความคิดเห็น @Todor ฉันจะเพิ่มว่าหากมีเงื่อนไขการสืบค้นเพิ่มเติมพวกเขาจะต้องเพิ่มในจากและในซ้ายเข้าร่วม สิ่งที่ต้องการ: จาก (เลือก * จากบุคคลที่อายุ = 32) o ซ้ายเข้าร่วม (เลือก * จากบุคคลที่อายุ! = 32) b - ถ้าคุณต้องการยกเลิกคนที่อายุ 32
Alain Zelink

1
@AlainZelink ไม่ใช่ "เงื่อนไขการสืบค้นเพิ่มเติม" เหล่านี้ควรใส่ไว้ในรายการเงื่อนไข WHERE สุดท้ายเพื่อไม่แนะนำเคียวรีย่อย - ไม่จำเป็นต้องใช้ใน @ axiac answer เดิมหรือไม่
tarilabs

5
วิธีนี้ใช้ได้ผล อย่างไรก็ตามจะเริ่มรับรายงานในบันทึกการสืบค้นที่ช้าเมื่อพยายามใช้ 10,000 แถวที่ใช้ ID เดียวกัน เข้าร่วมในคอลัมน์ที่จัดทำดัชนีแล้ว กรณีที่หายาก แต่คิดว่ามันคุ้มค่าพูดถึง
chaseisabelle

50

คุณสามารถเข้าร่วมกับแบบสอบถามย่อยที่ดึงมาและMAX(Group) Ageวิธีนี้เป็นวิธีพกพาข้าม RDBMS ส่วนใหญ่

SELECT t1.*
FROM yourTable t1
INNER JOIN
(
    SELECT `Group`, MAX(Age) AS max_age
    FROM yourTable
    GROUP BY `Group`
) t2
    ON t1.`Group` = t2.`Group` AND t1.Age = t2.max_age;

Michael ขอบคุณสำหรับสิ่งนี้ - แต่คุณมีคำตอบสำหรับปัญหาการส่งคืนความสัมพันธ์หลายแถวต่อความคิดเห็นของชาวโบฮีเมียหรือไม่?
Yarin

1
@Yarin หากมีตัวอย่าง 2 แถวที่ซึ่งGroup = 2, Age = 20แบบสอบถามย่อยจะส่งกลับหนึ่งแถว แต่ONข้อเชื่อมต่อจะจับคู่ทั้งคู่ดังนั้นคุณจะได้รับ 2 แถวกลับมาพร้อมกับกลุ่ม / อายุเดียวกันแม้ว่าจะมี vals ที่แตกต่างกันสำหรับคอลัมน์อื่น มากกว่าหนึ่ง
Michael Berkowski

ดังนั้นเราจึงบอกว่าเป็นไปไม่ได้ที่จะ จำกัด ผลลัพธ์ให้ได้หนึ่งรายการต่อกลุ่มเว้นแต่ว่าเราจะใช้เส้นทางของ Bohemians MySQL เท่านั้น
Yarin

@Yarin ไม่เป็นไปไม่ได้เพียงแค่ต้องทำงานมากขึ้นหากมีคอลัมน์เพิ่มเติม - อาจเป็นอีกแบบสอบถามย่อยที่ซ้อนกันเพื่อดึงรหัสที่เกี่ยวข้องสูงสุดสำหรับแต่ละคู่เช่นกลุ่ม / อายุจากนั้นเข้าร่วมกับที่จะได้รับส่วนที่เหลือของแถวตามรหัส
Michael Berkowski

นี่ควรเป็นคำตอบที่ได้รับการยอมรับ (คำตอบที่ได้รับการยอมรับในปัจจุบันจะล้มเหลวใน RDBMS อื่น ๆ ส่วนใหญ่และในความเป็นจริงแล้วอาจล้มเหลวใน MySQL หลายเวอร์ชัน)
ทิม Biegeleisen

28

โซลูชันง่ายๆสำหรับ SQLite (และอาจเป็น MySQL):

SELECT *, MAX(age) FROM mytable GROUP BY `Group`;

อย่างไรก็ตามมันไม่ทำงานใน PostgreSQL และอาจเป็นแพลตฟอร์มอื่น ๆ

ใน PostgreSQL คุณสามารถใช้DISTINCT ON clause ได้:

SELECT DISTINCT ON ("group") * FROM "mytable" ORDER BY "group", "age" DESC;

@Bohemian ขอโทษฉันได้รับมันรู้ว่านี้คือ MySQL เท่านั้นในขณะที่มันรวมถึงคอลัมน์ที่ไม่รวม
Cec

2
@IgorKulagin - ไม่ทำงานใน Postgres- ข้อความแสดงข้อผิดพลาด: คอลัมน์ "mytable.id" จะต้องปรากฏใน GROUP BY clause หรือจะใช้ในฟังก์ชั่นรวม
Yarin

13
แบบสอบถาม MySQL อาจทำงานโดยบังเอิญได้หลายครั้ง "SELECT *" อาจส่งคืนข้อมูลที่ไม่สอดคล้องกับจำนวน MAX (อายุ) คำตอบนี้ผิด นี่อาจเป็นกรณีของ SQLite
Albert Hendriks

2
แต่นี่เหมาะกับกรณีที่เราต้องเลือกคอลัมน์ที่จัดกลุ่มและคอลัมน์สูงสุด สิ่งนี้ไม่เหมาะกับข้อกำหนดข้างต้นที่จะให้ผลลัพธ์ ('Bob', 1, 42) แต่ผลลัพธ์ที่คาดหวังคือ ('Shawn', 1, 42)
Ram Babu S

1
เหมาะสำหรับ postgres
Karol Gasienica

4

ใช้วิธีการจัดอันดับ

SELECT @rn :=  CASE WHEN @prev_grp <> groupa THEN 1 ELSE @rn+1 END AS rn,  
   @prev_grp :=groupa,
   person,age,groupa  
FROM   users,(SELECT @rn := 0) r        
HAVING rn=1
ORDER  BY groupa,age DESC,person

sel - ต้องการคำอธิบาย - ฉันไม่เคยเห็น:=มาก่อน - นั่นคืออะไร?
Yarin

1
: = เป็นผู้ดำเนินการที่ได้รับมอบหมาย คุณสามารถอ่านเพิ่มเติมได้ที่dev.mysql.com/doc/refman/5.0/en/user-variables.html
sel

ฉันจะต้องขุดลงไปในนี้ - ฉันคิดว่าคำตอบที่ซับซ้อนสถานการณ์ของเรา แต่ขอบคุณสำหรับการสอนฉันสิ่งใหม่ ..
Yarin

3

ไม่แน่ใจว่า MySQL มีฟังก์ชัน row_number หรือไม่ ถ้าเป็นเช่นนั้นคุณสามารถใช้มันเพื่อให้ได้ผลลัพธ์ที่ต้องการ บน SQL Server คุณสามารถทำสิ่งที่คล้ายกับ:

CREATE TABLE p
(
 person NVARCHAR(10),
 gp INT,
 age INT
);
GO
INSERT  INTO p
VALUES  ('Bob', 1, 32);
INSERT  INTO p
VALUES  ('Jill', 1, 34);
INSERT  INTO p
VALUES  ('Shawn', 1, 42);
INSERT  INTO p
VALUES  ('Jake', 2, 29);
INSERT  INTO p
VALUES  ('Paul', 2, 36);
INSERT  INTO p
VALUES  ('Laura', 2, 39);
GO

SELECT  t.person, t.gp, t.age
FROM    (
         SELECT *,
                ROW_NUMBER() OVER (PARTITION BY gp ORDER BY age DESC) row
         FROM   p
        ) t
WHERE   t.row = 1;

1
มันทำตั้งแต่ 8.0
Ilja Everilä

2

ทางออกของแอกเซียเป็นสิ่งที่ดีที่สุดสำหรับฉันในที่สุด ฉันมีความซับซ้อนเพิ่มขึ้นอย่างไรก็ตาม: "ค่าสูงสุด" จากการคำนวณสองคอลัมน์

ลองใช้ตัวอย่างเดียวกัน: ฉันต้องการคนที่เก่าแก่ที่สุดในแต่ละกลุ่ม หากมีคนที่อายุเท่ากันให้พาคนที่สูงที่สุด

ฉันต้องดำเนินการด้านซ้ายเข้าร่วมสองครั้งเพื่อให้ได้พฤติกรรมนี้:

SELECT o1.* WHERE
    (SELECT o.*
    FROM `Persons` o
    LEFT JOIN `Persons` b
    ON o.Group = b.Group AND o.Age < b.Age
    WHERE b.Age is NULL) o1
LEFT JOIN
    (SELECT o.*
    FROM `Persons` o
    LEFT JOIN `Persons` b
    ON o.Group = b.Group AND o.Age < b.Age
    WHERE b.Age is NULL) o2
ON o1.Group = o2.Group AND o1.Height < o2.Height 
WHERE o2.Height is NULL;

หวังว่านี่จะช่วยได้! ฉันคิดว่าน่าจะมีวิธีที่ดีกว่าในการทำเช่นนี้ ...


2

โซลูชันของฉันใช้งานได้เฉพาะเมื่อคุณต้องการดึงข้อมูลเพียงหนึ่งคอลัมน์อย่างไรก็ตามสำหรับความต้องการของฉันเป็นโซลูชันที่ดีที่สุดที่พบในแง่ของประสิทธิภาพ (ใช้เพียงแบบสอบถามเดียว!):

SELECT SUBSTRING_INDEX(GROUP_CONCAT(column_x ORDER BY column_y),',',1) AS xyz,
   column_z
FROM table_name
GROUP BY column_z;

มันใช้ GROUP_CONCAT เพื่อสร้างรายการ concat ที่เรียงลำดับแล้วฉันจะซับสตริงให้กับรายการแรกเท่านั้น


สามารถยืนยันได้ว่าคุณจะได้รับหลายคอลัมน์โดยการเรียงลำดับบนคีย์เดียวกันภายใน group_concat แต่ต้องเขียน group_concat / index / substring แยกสำหรับแต่ละคอลัมน์
Rasika

โบนัสที่นี่คือคุณสามารถเพิ่มหลายคอลัมน์ในการจัดเรียงภายใน group_concat และมันจะแก้ไขความสัมพันธ์ได้อย่างง่ายดายและรับประกันเพียงหนึ่งระเบียนต่อกลุ่ม ทำได้ดีในวิธีที่ง่ายและมีประสิทธิภาพ!
Rasika

2

ฉันมีวิธีแก้ปัญหาง่ายๆโดยใช้ WHERE IN

SELECT a.* FROM `mytable` AS a    
WHERE a.age IN( SELECT MAX(b.age) AS age FROM `mytable` AS b GROUP BY b.group )    
ORDER BY a.group ASC, a.person ASC

1

การใช้ CTEs - นิพจน์ตารางทั่วไป:

WITH MyCTE(MaxPKID, SomeColumn1)
AS(
SELECT MAX(a.MyTablePKID) AS MaxPKID, a.SomeColumn1
FROM MyTable1 a
GROUP BY a.SomeColumn1
  )
SELECT b.MyTablePKID, b.SomeColumn1, b.SomeColumn2 MAX(b.NumEstado)
FROM MyTable1 b
INNER JOIN MyCTE c ON c.MaxPKID = b.MyTablePKID
GROUP BY b.MyTablePKID, b.SomeColumn1, b.SomeColumn2

--Note: MyTablePKID is the PrimaryKey of MyTable

1

ใน Oracle ด้านล่างแบบสอบถามสามารถให้ผลลัพธ์ที่ต้องการ

SELECT group,person,Age,
  ROWNUMBER() OVER (PARTITION BY group ORDER BY age desc ,person asc) as rankForEachGroup
  FROM tablename where rankForEachGroup=1

0
with CTE as 
(select Person, 
[Group], Age, RN= Row_Number() 
over(partition by [Group] 
order by Age desc) 
from yourtable)`


`select Person, Age from CTE where RN = 1`

0

คุณสามารถลอง

SELECT * FROM mytable WHERE age IN (SELECT MAX(age) FROM mytable GROUP BY `Group`) ;

1
ขอบคุณแม้ว่านี่จะส่งกลับหลายระเบียนสำหรับอายุเมื่อมีการผูก
Yarin

นอกจากนี้แบบสอบถามนี้จะไม่ถูกต้องในกรณีที่มีกลุ่มอายุ 39 ปีในกรณีที่ 1 บุคคลนั้นจะถูกเลือกด้วยแม้ว่าอายุสูงสุดในกลุ่ม 1 จะสูงกว่าก็ตาม
Joshua Richardson

0

ฉันจะไม่ใช้กลุ่มเป็นชื่อคอลัมน์เนื่องจากเป็นคำที่สงวนไว้ อย่างไรก็ตามการติดตาม SQL จะใช้งานได้

SELECT a.Person, a.Group, a.Age FROM [TABLE_NAME] a
INNER JOIN 
(
  SELECT `Group`, MAX(Age) AS oldest FROM [TABLE_NAME] 
  GROUP BY `Group`
) b ON a.Group = b.Group AND a.Age = b.oldest

ขอบคุณแม้ว่านี่จะส่งกลับหลายระเบียนสำหรับอายุเมื่อมีการผูกกัน
Yarin

@Yarin จะตัดสินได้อย่างไรว่าใครคือคนโตที่ถูกต้องที่สุด ดูเหมือนว่าคำตอบหลายคำตอบจะเป็นคำตอบที่ถูกต้องมิฉะนั้นจะใช้การ จำกัด และการสั่งซื้อ
Duncan

0

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

ที่มา: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

SELECT person, group,
    GROUP_CONCAT(
        DISTINCT age
        ORDER BY age DESC SEPARATOR ', follow up: '
    )
FROM sql_table
GROUP BY group;

0

ให้ชื่อตารางเป็นคน

select O.*              -- > O for oldest table
from people O , people T
where O.grp = T.grp and 
O.Age = 
(select max(T.age) from people T where O.grp = T.grp
  group by T.grp)
group by O.grp; 

0

หากต้องการ ID (และ coulmns ทั้งหมด) จาก mytable

SELECT
    *
FROM
    mytable
WHERE
    id NOT IN (
        SELECT
            A.id
        FROM
            mytable AS A
        JOIN mytable AS B ON A. GROUP = B. GROUP
        AND A.age < B.age
    )

0

นี่คือวิธีที่ฉันได้รับจำนวนแถวสูงสุด N แถวต่อกลุ่มใน mysql

SELECT co.id, co.person, co.country
FROM person co
WHERE (
SELECT COUNT(*)
FROM person ci
WHERE  co.country = ci.country AND co.id < ci.id
) < 1
;

มันทำงานอย่างไร:

  • เข้าร่วมตารางด้วยตนเอง
  • กลุ่มทำโดย co.country = ci.country
  • องค์ประกอบ N ต่อกลุ่มถูกควบคุมโดย ) < 1ดังนั้นสำหรับ 3 องค์ประกอบ -) <3
  • การรับค่า max หรือ min ขึ้นอยู่กับ: co.id < ci.id
    • co.id <ci.id - สูงสุด
    • co.id> ci.id - นาที

ตัวอย่างเต็มรูปแบบที่นี่:

mysql เลือก n ค่าสูงสุดต่อกลุ่ม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.