I have a table that contains multiple records for each day of the month, over a number of years. Can someone help me out in writing a query that will only return the last day of each month.
-
1many times duplicate - please search SO – Mitch Wheat May 03 '11 at 06:51
-
1see in related section of your question. I'm sure you will find answer there. – Harry Joy May 03 '11 at 06:51
-
possible duplicate of [Get the last day of the month in SQL](http://stackoverflow.com/questions/1051488/get-the-last-day-of-the-month-in-sql) – codingbadger May 03 '11 at 06:53
-
@Barry: That's not exactly what he's asking. – Tomalak May 03 '11 at 06:56
-
All those results are just for a single month.. As in MAX(date) I'm trying to do that but over multiple years.. Its slightly more complicated... – Matt May 03 '11 at 07:14
9 Answers
SQL Server (other DBMS will work the same or very similarly):
SELECT
*
FROM
YourTable
WHERE
DateField IN (
SELECT MAX(DateField)
FROM YourTable
GROUP BY MONTH(DateField), YEAR(DateField)
)
An index on DateField
is helpful here.
PS: If your DateField
contains time values, the above will give you the very last record of every month, not the last day's worth of records. In this case use a method to reduce a datetime to its date value before doing the comparison, for example this one.
-
1For **PostgreSQL** you need to use: `GROUP BY EXTRACT(MONTH FROM DateField), EXTRACT(YEAR FROM DateField)`. – Tadeu Sampaio Jun 03 '21 at 11:38
-
if it's can help someone i just convert mydatetime to date then i did a compariaosn `SELECT * FROM Table_ WHERE CONVERT(VARCHAR(10), yourDateTime, 111) IN ( SELECT MAX(CONVERT(VARCHAR(10), yourDateTime, 111)) AS LastDay FROM Table_ GROUP BY YEAR(yourDateTime), MONTH(yourDateTime))` – satcha Sep 17 '21 at 17:24
The easiest way I could find to identify if a date field in the table is the end of the month, is simply adding one day and checking if that day is 1.
where DAY(DATEADD(day, 1, AsOfDate)) = 1
If you use that as your condition (assuming AsOfDate is the date field you are looking for), then it will only returns records where AsOfDate is the last day of the month.

- 123
- 1
- 7
-
I found this to be the cleanest solution for me; what's the best way to include the row for the last date in the table? where (DAY(DATEADD(day, 1, AsOfDate)) = 1 or AsOfDate = (select max(AsOfDate) from [Table]))? – ScottFoster1000 Jan 10 '18 at 22:49
-
That should do it, yeah. That way you would return either the last day of the month or the last day you have available. Only problem is that you might end up with multiple results, not sure if that's a concern or not – Javier Rapoport Jan 12 '18 at 00:23
-
Thanks, good point re multiple results; just to note, in my final solution, I set the max datetime to a variable at the top of the script and use that in the where test for performance. – ScottFoster1000 Jan 12 '18 at 21:00
-
-
This @JavierRapoport answer will give **wrong results if the database contains only weekdays**. The @Tomalak selected answer above with `GROUP BY` is better because it will always give the correct results, regardless of the data on the database. – Tadeu Sampaio Jun 03 '21 at 11:42
-
@TadeuSampaio - agreed that it's not a generic answer, but based on the question as it was presented ("multiple records for each day of the month"), then assuming that there's a record for each day is not a bad assumption, and this logic is the simplest without having to rely in grouping/subquerying – Javier Rapoport Jun 05 '21 at 01:07
Use the EOMONTH() function if it's available to you (E.g. SQL Server). It returns the last date in a month given a date.
select distinct
Date
from DateTable
Where Date = EOMONTH(Date)
Or, you can use some date math.
select distinct
Date
from DateTable
where Date = DATEADD(MONTH, DATEDIFF(MONTH, -1, Date)-1, -1)

- 6,735
- 7
- 49
- 57
In SQL Server, this is how I usually get to the last day of the month relative to an arbitrary point in time:
select dateadd(day,-day(dateadd(month,1,current_timestamp)) , dateadd(month,1,current_timestamp) )
In a nutshell:
- From your reference point-in-time,
- Add 1 month,
- Then, from the resulting value, subtract its day-of-the-month in days.
Voila! You've the the last day of the month containing your reference point in time.
Getting the 1st day of the month is simpler:
select dateadd(day,-(day(current_timestamp)-1),current_timestamp)
- From your reference point-in-time,
- subtract (in days), 1 less than the current day-of-the-month component.
Stripping off/normalizing the extraneous time component is left as an exercise for the reader.

- 71,308
- 16
- 93
- 135
This should work on Oracle DB
select distinct last_day(trunc(sysdate - rownum)) dt
from dual
connect by rownum < 430
order by 1
I did the following and it worked out great. I also wanted the Maximum Date for the Current Month. Here is what I my output is. Notice the last date for July which is 24th. I pulled it on 7/24/2017, hence the result
Year Month KPI_Date
2017 4 2017-04-28
2017 5 2017-05-31
2017 6 2017-06-30
2017 7 2017-07-24
SELECT B.Year ,
B.Month ,
MAX(DateField) KPI_Date
FROM Table A
INNER JOIN ( SELECT DISTINCT
YEAR(EOMONTH(DateField)) year ,
MONTH(EOMONTH(DateField)) month
FROM Table
) B ON YEAR(A.DateField) = B.year
AND MONTH(A.DateField) = B.Month
GROUP BY B.Year ,
B.Month

- 559
- 5
- 8
SELECT * FROM YourTableName WHERE anyfilter
AND "DATE" IN (SELECT MAX(NameofDATE_Column) FROM YourTableName WHERE
anyfilter GROUP BY
TO_CHAR(NameofDATE_Column,'MONTH'),TO_CHAR(NameofDATE_Column,'YYYY'));
Note: this answer does apply for Oracle DB

- 127
- 1
- 1
- 15
Here's how I just solved this. day_date
is the date field, calendar
is the table that holds the dates.
SELECT cast(datepart(year, day_date) AS VARCHAR)
+ '-'
+ cast(datepart(month, day_date) AS VARCHAR)
+ '-'
+ cast(max(DATEPART(day, day_date)) AS VARCHAR) 'DATE'
FROM calendar
GROUP BY datepart(year, day_date)
,datepart(month, day_date)
ORDER BY 1

- 545
- 2
- 20
A simple way to get the last day of month is to get the first day of the next month and subtract 1.

- 321,842
- 108
- 597
- 820
-
1
-
@FistOfFury It's a pointer how to solve it. Since there no standard compliant SQL database, I can't give you working SQL code until you tell me which database you use. – Aaron Digulla Apr 19 '16 at 12:26