I'm doing a review of existing code and have found the following SQL query which is used to get a selection of records last month.
Is there a more concise way of writing SQL to do what this date based clause does in MySQL?
SELECT foo
FROM some_table
WHERE some_date
BETWEEN
DATE_FORMAT(LAST_DAY((NOW() - INTERVAL 1 MONTH) - INTERVAL 1 SECOND), '%Y-%m-01 00:00:00')
AND
DATE_FORMAT(LAST_DAY((NOW() - INTERVAL 1 MONTH) - INTERVAL 1 SECOND), '%Y-%m-%d 23:59:59')
It works, but I just twitch a little every time I see it.
Can anyone else write it better?
Thank you in advance.
There's no need to format the dates, they default to YYYY-MM-DD 00:00:00.
This is a little bit simpler:
SELECT foo
FROM some_table
WHERE some_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
AND some_date < LAST_DAY(CURDATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY
So if CURDATE() is today, 2019-02-06, then:
- INTERVAL 2 MONTH is 2018-12-06
LAST_DAY() of that date is 2018-12-31
+ INTERVAL 1 DAY is 2019-01-01
Then the upper bound is:
- INTERVAL 1 MONTH is 2019-1-06
LAST_DAY() of that date is 2019-1-31
+ INTERVAL 1 DAY is 2019-02-01
The dates should be strictly less than 2019-02-01.
Using less than accounts for timestamps in the last second of the month, between 23:59:59.000 and 23:59:59.999.
I have a table containing data about events and festivals with following columns recording their start and end dates.
Start_Date
End_Date
date format is in YYYY-MM-DD. I need to fetch event details with the following condition.
Need to fetch all events which start with a current month and there end dates can be anything say currentDate+next30days.
I am clear about end date concept. but not sure how I can fetch data whose start dates are in a current month.
For this, I need to compare current year and current month against the Start_Date column in my database.
Can anyone help me to point out as how I can do that?
select * from your_table
where year(Start_Date) = year(curdate())
and month(Start_Date) = month(curdate())
and end_date <= curdate() + interval 30 day
I don't like either of the other two answers, because they do not let the optimizer use an index on start_date. For that, the functions need to be on the current date side.
So, I would go for:
where start_date >= date_add(curdate(), interval 1 - day(curdate()) day) and
start_date < date_add(date_add(curdate(), interval 1 - day(curdate()) day), interval 1 month)
All the date functions are on curdate(), which does not affect the ability of MySQL to use an index in this case.
You can also include the condition on end_date:
where (start_date >= date_add(curdate(), interval 1 - day(curdate()) day) and
start_date < date_add(date_add(curdate(), interval 1 - day(curdate()) day), interval 1 month)
) and
end_date <= date_add(curdate(), interval 30 day)
This can still take advantage of an index.
DateTime functions are your friends:
SELECT
*
FROM
`event`
WHERE
(MONTH(NOW()) = MONTH(`Start_Date`))
AND
(`End_Date` <= (NOW() + INTERVAL 30 DAY))
AND
(YEAR(NOW()) = YEAR(`Start_Date`))
Comparing the year and month separately feels messy. I like to contain it in one line. I doubt it will make a noticeable difference in performance, so its purely personal preference.
select * from your_table
where LAST_DAY(Start_Date) = LAST_DAY(curdate())
and end_date <= curdate() + interval 30 day
So all I'm doing is using the last_day function to check the last day of the month of each date and then comparing this common denominator. You could also use
where DATE_FORMAT(Start_Date ,'%Y-%m-01') = DATE_FORMAT(curdate(),'%Y-%m-01')
I want to run a MYSQL query to get data for the previous week. The datatype for the date column is DATETIME. Could anyone suggest?
SELECT *
FROM calendar
WHERE dt BETWEEN CURDATE()-INTERVAL 1 WEEK AND CURDATE();
Here is an another version:
SELECT * FROM table WHERE
YEARWEEK(`date`, 1) = YEARWEEK( CURDATE() - INTERVAL 1 WEEK, 1)
SELECT id FROM tbl
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate())-1 DAY
Here is the solution I find most reliable for getting data between the previus monday to the current monday. (That is what most people mean when the say past week, but not all, and that reflect in mysql).
SELECT
*
FROM
table
WHERE
date BETWEEN
(CURDATE() - INTERVAL 1 DAY) + INTERVAL -1 WEEK - INTERVAL WEEKDAY((CURDATE() - INTERVAL 1 DAY)) DAY
and
(CURDATE() - INTERVAL 1 DAY) + INTERVAL 0 WEEK - INTERVAL WEEKDAY((CURDATE() - INTERVAL 1 DAY)) DAY
It's also easy to change it for another week intervall
Make variable for current datetime - 1 week and make this query:
SELECT * FROM table WHERE date > $datatime
I need to select data from MySQL database between the 1st day of the current month and current day.
select*from table_name
where date between "1st day of current month" and "current day"
Can someone provide working example of this query?
select * from table_name
where (date between DATE_ADD(LAST_DAY(DATE_SUB(CURDATE(), interval 30 day), interval 1 day) AND CURDATE() )
Or better :
select * from table_name
where (date between DATE_FORMAT(NOW() ,'%Y-%m-01') AND NOW() )
I was looking for a similar query where I needed to use the first day of a month in my query.
The last_day function didn't work for me but DAYOFMONTH came in handy.
So if anyone is looking for the same issue, the following code returns the date for first day of the current month.
SELECT DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY);
Comparing a date column with the first day of the month :
select * from table_name where date between
DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY) and CURRENT_DATE
select * from table_name
where `date` between curdate() - dayofmonth(curdate()) + 1
and curdate()
SQLFiddle example
I have used the following query. It has worked great for me in the past.
select date(now()) - interval day(now()) day + interval 1 day
try this :
SET #StartDate = DATE_SUB(DATE(NOW()),INTERVAL (DAY(NOW())-1) DAY);
SET #EndDate = ADDDATE(CURDATE(),1);
select * from table where (date >= #StartDate and date < #EndDate);
Complete solution for mysql current month and current year, which makes use of indexing properly as well :)
-- Current month
SELECT id, timestampfield
FROM table1
WHERE timestampfield >= DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY)
AND timestampfield <= LAST_DAY(CURRENT_DATE);
-- Current year
SELECT id, timestampfield
FROM table1
WHERE timestampfield >= DATE_SUB(CURRENT_DATE, INTERVAL DAYOFYEAR(CURRENT_DATE)-1 DAY)
AND timestampfield <= LAST_DAY(CURRENT_DATE);
select * from table
where date between
(date_add (CURRENT_DATE, INTERVAL(1 - DAYOFMonth(CURRENT_DATE)) day)) and current_date;
select * from <table>
where <dateValue> between last_day(curdate() - interval 1 month + interval 1 day)
and curdate();
I found myself here after needing this same query for some Business Intelligence Queries I'm running on an e-commerce store. I wanted to add my solution as it may be helpful to others.
set #firstOfLastLastMonth = DATE_SUB(LAST_DAY(DATE_ADD(NOW(), INTERVAL -2 MONTH)),INTERVAL DAY(LAST_DAY(DATE_ADD(NOW(), INTERVAL -2 MONTH)))-1 DAY);
set #lastOfLastLastMonth = LAST_DAY(DATE_ADD(NOW(), INTERVAL -2 MONTH));
set #firstOfLastMonth = DATE_SUB(LAST_DAY(DATE_ADD(NOW(), INTERVAL -1 MONTH)),INTERVAL DAY(LAST_DAY(DATE_ADD(NOW(), INTERVAL -1 MONTH)))-1 DAY);
set #lastOfLastMonth = LAST_DAY(DATE_ADD(NOW(), INTERVAL -1 MONTH));
set #firstOfMonth = DATE_ADD(#lastOfLastMonth, INTERVAL 1 DAY);
set #today = CURRENT_DATE;
Today is 2019-10-08 so the output looks like
#firstOfLastLastMonth = '2019-08-01'
#lastOfLastLastMonth = '2019-08-31'
#firstOfLastMonth = '2019-09-01'
#lastOfLastMonth = '2019-09-30'
#firstOfMonth = '2019-10-01'
#today = '2019-10-08'
A less orthodox approach might be
SELECT * FROM table_name
WHERE LEFT(table_name.date, 7) = LEFT(CURDATE(), 7)
AND table_name.date <= CURDATE();
as a date being between the first of a month and now is equivalent to a date being in this month, and before now. I do feel that this is a bit easier on the eyes than some other approaches, though.
SELECT date_sub(current_date(),interval dayofmonth(current_date())-1 day) as first_day_of_month;
I had some what similar requirement - to find first day of the month but based on year end month selected by user in their profile page.
Problem statement - find all the txns done by the user in his/her financial year. Financial year is determined using year end month value where month can be any valid month - 1 for Jan, 2 for Feb, 3 for Mar,....12 for Dec.
For some clients financial year ends on March and some observe it on December.
Scenarios - (Today is `08 Aug, 2018`)
1. If `financial year` ends on `July` then query should return `01 Aug 2018`.
2. If `financial year` ends on `December` then query should return `01 January 2018`.
3. If `financial year` ends on `March` then query should return `01 April 2018`.
4. If `financial year` ends on `September` then query should return `01 October 2017`.
And, finally below is the query. -
select #date := (case when ? >= month(now())
then date_format((subdate(subdate(now(), interval (12 - ? + month(now()) - 1) month), interval day(now()) - 2 day)) ,'%Y-%m-01')
else date_format((subdate(now(), interval month(now()) - ? - 1 month)), '%Y-%m-01') end)
where ? is year end month (values from 1 to 12).
The key here is to get the first day of the month. For that, there are several options. In terms of performance, our tests show that there isn't a significant difference between them - we wrote a whole blog article on the topic. Our findings show that what really matters is whether you need the result to be VARCHAR, DATETIME, or DATE.
The fastest solution to the real problem of getting the first day of the month returns VARCHAR:
SELECT CONCAT(LEFT(CURRENT_DATE, 7), '-01') AS first_day_of_month;
The second fastest solution gives a DATETIME result - this runs about 3x slower than the previous:
SELECT TIMESTAMP(CONCAT(LEFT(CURRENT_DATE, 7), '-01')) AS first_day_of_month;
The slowest solutions return DATE objects. Don't believe me? Run this SQL Fiddle and see for yourself 😊
In your case, since you need to compare the value with other DATE values in your table, it doesn't really matter what methodology you use because MySQL will do the conversion implicitly even if your formula doesn't return a DATE object.
So really, take your pick. Which is most readable for you? I'd pick the first since it's the shortest and arguably the simplest:
SELECT * FROM table_name
WHERE date BETWEEN CONCAT(LEFT(CURRENT_DATE, 7), '-01') AND CURDATE;
SELECT * FROM table_name
WHERE date BETWEEN DATE(CONCAT(LEFT(CURRENT_DATE, 7), '-01')) AND CURDATE;
SELECT * FROM table_name
WHERE date BETWEEN (LAST_DAY(CURRENT_DATE) + INTERVAL 1 DAY - INTERVAL 1 MONTH) AND CURDATE;
SELECT * FROM table_name
WHERE date BETWEEN (DATE(CURRENT_DATE) - INTERVAL (DAYOFMONTH(CURRENT_DATE) - 1) DAY) AND CURDATE;
SELECT * FROM table_name
WHERE date BETWEEN (DATE(CURRENT_DATE) - INTERVAL (DAYOFMONTH(CURRENT_DATE)) DAY + INTERVAL 1 DAY) AND CURDATE;
SELECT * FROM table_name
WHERE date BETWEEN DATE_FORMAT(CURRENT_DATE,'%Y-%m-01') AND CURDATE;
I used this one
select DATE_ADD(DATE_SUB(LAST_DAY(now()), INTERVAL 1 MONTH),INTERVAL 1 day) first_day
,LAST_DAY(now()) last_day, date(now()) today_day
All the responses here have been way too complex. You know that the first of the current month is the current date but with 01 as the date. You can just use YEAR() and MONTH() to build the month date by inputting the NOW() method.
Here's the solution:
select * from table_name
where date between CONCAT_WS('-', YEAR( NOW() ), MONTH( NOW() ), '01') and DATE( NOW() )
CONCAT_WS() joins a series of strings with a separator (a dash in this case).
So if today is 2020-08-28, YEAR( NOW() ) = '2020' and MONTH( NOW() ) = '08' and then you just need to append '01' at the end.
Voila!
Get first date and last date from month and year.
select LAST_DAY(CONCAT(year,'.',month,'.','01')) as registerDate from user;
select date_add(date_add(LAST_DAY(end_date),interval 1 DAY),interval -1 MONTH) AS closingDate from user;
SET #date:='2012-07-11';
SELECT date_add(date_add(LAST_DAY(#date),interval 1 DAY),
interval -1 MONTH) AS first_day
I have a field named timestamp. This is the last time a member was logged in.
I am looking to include a where clause in a query for something like
WHERE timestamp > todays date - 6 weeks
How would I do this?
I am trying to only include users that have logged in in the last 6 weeks.
Thanks
I find this syntax more readable than date_sub, but either way works.
WHERE timestamp >= NOW() - INTERVAL 6 WEEK
If you want to go by "Today" (midnight) instead "now" (current time), you would use this
WHERE timestamp >= DATE(NOW()) - INTERVAL 6 WEEK
where column>=date_sub(now(), interval 6 week)
This link demonstrates how you might acquire a timestamp of yesterday using the format DATE_ADD(CURDATE(), INTERVAL -1 DAY), therefore your query would probably be:
WHERE timestamp > DATE_ADD(CURDATE(), INTERVAL -42 DAY)
You can use between and now():
select somevalue
from yourtable
where yourtimestamp between now() - interval 1 day and now()
for TIMESTAMP there is a TIMESTAMPADD() function
SELECT TIMESTAMPADD(WEEK, -6, CURRENT_TIMESTAMP)
this will return the timestemp of 6 weeks ago
or in the case like the question
SELECT * FROM users
WHERE lastlogin > TIMESTAMPADD(WEEK, -6, CURRENT_TIMESTAMP)
Any luck yet. Have you tried:
>= DATE_SUB(NOW(), INTERVAL 6 WEEK)