'Select records based on last date

Based on the table called Course below:

enter image description here

How can I select records which have course name with latest date? I mean if I have two same course names for one ID, I should only show the latest one as the below result.

Simply, I want only to show the latest row per ("ID", "Course Name").

enter image description here

And what if I have two date columns in Course table, which are StartDate & EndDate and I want to show the same based on EndDate only.?

I am using PostgreSQL.



Solution 1:[1]

In PostgreSQL, to get unique rows for a defined set of columns, the preferable technique is generally DISTINCT ON:

SELECT DISTINCT ON ("ID") *
FROM   "Course"
ORDER  BY "ID", "Course Date" DESC NULLS LAST, "Course Name";

Assuming you actually use those unfortunate upper case identifiers with spaces.

You get exactly one row per ID this way - the one with the latest known "Course Date" and the first "Course Name" (according to sort order) in case of ties on the date.

You can drop NULLS LAST if your column is defined NOT NULL.

To get unique rows per ("ID", "Course Name"):

SELECT DISTINCT ON ("ID", "Course Name") *
FROM   "Course"
ORDER  BY "ID", "Course Name", "Course Date" DESC NULLS LAST;

Details in this related answer:

Solution 2:[2]

SELECT "ID", "Course Name", MAX("Course Date") FROM "Course" GROUP BY "ID", "Course Name"

Solution 3:[3]

SELECT *
FROM (SELECT ID, CourseName, CourseDate, 
      MAX(CourseDate) OVER (PARTITION BY COURSENAME) as MaxCourseDate
FROM Course) x
WHERE CourseDate = MaxCourseDate

Here the MAX() OVER(PARTITION BY) allows you to find the highest CourseDate for each Course (the partition) in a derived table. Then you can just select for the rows where the CourseDate is equal to the maximum Coursedate found for that Course.

This approach has the benefit of not using a GROUP BY clause, which would restrict which columns you could return since any non-aggregrate column in the SELECT clause would also have to be in the GROUP BY clause.

Solution 4:[4]

Try this:

SELECT DISTINCT ON (c."Id", c."Course Name") 
    c."Id", c."Course Name", c."Course Date" 
FROM (SELECT * FROM "Course" ORDER BY "Course Date" DESC) c;

Solution 5:[5]

SELECT * 
FROM  course
GROUP BY id,course name
order by course_date desc

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Maxim Krizhanovsky
Solution 3 GVIrish
Solution 4
Solution 5 a_horse_with_no_name