จะเลือก id ด้วย max date group ตามหมวดหมู่ใน PostgreSQL ได้อย่างไร?


91

ตัวอย่างเช่นฉันต้องการเลือก id ที่มีกลุ่มวันที่สูงสุดตามหมวดหมู่ผลลัพธ์คือ 7, 2, 6

id  category  date
1   a         2013-01-01
2   b         2013-01-03
3   c         2013-01-02
4   a         2013-01-02
5   b         2013-01-02
6   c         2013-01-03
7   a         2013-01-03
8   b         2013-01-01
9   c         2013-01-01

ฉันขอทราบวิธีการทำใน PostgreSQL ได้ไหม


4
ควรรวม PostgreSQL เวอร์ชันของคุณไว้ด้วย
Erwin Brandstetter

คำตอบ:


145

นี่เป็นกรณีการใช้งานที่สมบูรณ์แบบสำหรับDISTINCT ON- ส่วนขยายเฉพาะของ Postgres ของมาตรฐานDISTINCT:

SELECT DISTINCT ON (category)
       id  -- , category, date  -- any other column (expression) from the same row
FROM   tbl
ORDER  BY category, date DESC;

ระมัดระวังกับการเรียงลำดับจากมากไปหาน้อย หากคอลัมน์เป็นโมฆะคุณอาจต้องการเพิ่มNULLS LAST:

DISTINCT ONง่ายและรวดเร็ว คำอธิบายโดยละเอียดในคำตอบที่เกี่ยวข้องนี้:

สำหรับตารางขนาดใหญ่ที่มีหลายแถวให้categoryพิจารณาแนวทางอื่น:


ดูเหมือนจะดี แต่คุณแน่ใจหรือไม่ว่าจะรับประกันได้ว่าจะใช้ได้ทุกครั้ง
Atherion

@Tixel: แน่นอน ตามลิงค์สำหรับรายละเอียดเพิ่มเติม
Erwin Brandstetter

21

ลองอันนี้:

SELECT t1.* FROM Table1 t1
JOIN 
(
   SELECT category, MAX(date) AS MAXDATE
   FROM Table1
   GROUP BY category
) t2
ON T1.category = t2.category
AND t1.date = t2.MAXDATE

ดูSQLFiddle นี้


1
มีตัวเลือกอื่นโดยใช้ฟังก์ชันหน้าต่างอันดับ ()
Denis de Bernardy

@ user1735921: คุณจะได้รับคอลัมน์ทั้งหมดจาก Table1 คุณสามารถเลือกได้ตามที่คุณต้องการ
Himanshu Jansari

16

อีกวิธีหนึ่งคือการใช้first_valueฟังก์ชันหน้าต่าง: http://sqlfiddle.com/#!12/7a145/14

SELECT DISTINCT
  first_value("id") OVER (PARTITION BY "category" ORDER BY "date" DESC) 
FROM Table1
ORDER BY 1;

... แม้ว่าฉันสงสัยว่าคำแนะนำของ hims056 มักจะทำงานได้ดีกว่าเมื่อมีดัชนีที่เหมาะสม

วิธีที่สามคือ:

SELECT
  id
FROM (
  SELECT
    id,
    row_number() OVER (PARTITION BY "category" ORDER BY "date" DESC) AS rownum
  FROM Table1
) x
WHERE rownum = 1;

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