SQL Query for retreiving records that fall on the

2019-02-20 07:11发布

问题:

I have a table with records from many dates. I would like to perform a query that only returns records that fall on the last day of the date's month. Something like:

SELECT * FROM mytable
WHERE DATEPART(d, mytable.rdate) = DATEPART(d,DATEADD(m,1,DATEADD(d, -1, mytable.rdate)))

Except this doesn't work as the rdate in the right-hand side of the argument should be the last day of it's month for the dateadd to return the correct comparison.

Basically is there an concise way to do this comparison? An equivalent for quarter-ends would also be very helpful, but no doubt more complex.

EDIT:

Essentially I want to check if a given date is the last in whatever month (or quarter) it falls into. If it is, return that record. This would involve a some function to return the last day of the month of any date. e.g. lastdayofmonth('2013-06-10') = 30 (so this record would not be returned.

EDIT2:

For the case of returning the records that fall on the last day of the quarter they are in it would need to be something like:

SELECT * FROM mytable
WHERE DATEPART('d', mytable.rdate) = lastdayofmonth(mytable.rdate)
  AND DATEPART('m', mytable.rdate) = lastmonthofquarter(mytable.rdate);

The tricky bit is the lastdayofmonth() and lastmonthofquarter() functions

回答1:

Use the DateSerial Function to compute the last day of the month for a given date.

Passing zero as the third argument, day, actually returns the last date of the previous month.

rdate = #2013-7-24#
? DateSerial(Year(rdate), Month(rdate), 0)
6/30/2013 

So to get the last date from the rdate month, add 1 to the month argument.

? DateSerial(Year(rdate), Month(rdate) + 1, 0)
7/31/2013 

You might suspect that approach would break for a December rdate, since Month() + 1 would return 13. However, DateSerial still copes with it.

rdate = #2013-12-1#
? DateSerial(Year(rdate), Month(rdate) + 1, 0)
12/31/2013 

If you will be running your query from within an Access application session, you can build a VBA function based on that approach, and use the custom function in the query.

However, if the query will be run from an ODBC or OleDb connection to the Access db, the query can not use a VBA user-defined function. In that situation, you can use DateSerial directly in your query.

SELECT m.*
FROM mytable AS m
WHERE m.rdate = DateSerial(Year(m.rdate), Month(m.rdate) + 1, 0)

That should work if your rdate values all include midnight as the time component. If those values include other times, use DateValue.

WHERE DateValue(m.rdate) = DateSerial(Year(m.rdate), Month(m.rdate) + 1, 0)


回答2:

Try This.

SELECT * FROM mytable
WHERE DATEPART(d, mytable.rdate) = 
DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, GETDATE()) + 1, 0))


回答3:

Try this one, this is tested on MS Access:

Using String Concatenation:

SELECT * FROM mytable
WHERE 
DatePart('d',mytable.rdate) = 
DatePart('d',dateadd('m',1, "1/" & DatePart('m',mytable.rdate)  & "/" & DatePart('yyyy',mytable.rdate))-1);

Update without using string concatenation:

SELECT * FROM
(SELECT *,
DATEPART('d',DATEDIFF('m',0,mytable.rdate)+1,
DATEADD('m',1,
DATEADD('d',DATEDIFF('d',0,mytable.rdate)- DATEPART('d',mytable.rdate)+1,0))-1) as EOMonth
FROM mytable ) A
WHERE DATEPART('d',mytable.rdate) = DATEPART('d',EOMonth)