I did not find any of examples for MySQL - all of them were quite complicated.
How can I SELECT the first Sunday of the month?
So choose the first day of the month: 2012-01-01 (or whatever month and year you want).
Get the weekday index of the date. Indexes here are from 0 to 6.
Subtract that index from 6 and you will get how many days you need to add until the date is Sunday.
Add that amount of days to the chosen day.
SELECT DATE_ADD("2012-01-01 10:00:00", INTERVAL (6 - WEEKDAY("2012-01-01 10:00:00")) DAY);
Or:
SELECT DATE_ADD("2012-01-01", INTERVAL (6 - WEEKDAY("2012-01-01")) DAY);
So choose the first day of the month: 2021-08-01 (or whatever month and year you want).
SELECT ADDDATE( '2021-08-01' , MOD((8-DAYOFWEEK('2021-08-01')),7))
Related
For example, if i have search string "2017-12-14" then i need to find all rows that matches 7-day range: "%-12-11", "%-12-12", "%-12-13", "%-12-14", "%-12-15", "%-12-16", "%-12-17".
Is it possible to do with MySql only?
To select same day cross years you can use following trick.
get the list of last 7 days/1 week NOW() - INTERVAL 1 WEEK
get the DAYOFYEAR of that days
search the database for all values of the same day in year
.
SELECT * FROM timevalues
WHERE DAYOFYEAR(timefield) IN (
SELECT DAYOFYEAR(timefield)
FROM timevalues
WHERE DATE(timefield) BETWEEN NOW() - INTERVAL 1 WEEK AND NOW()
)
;
Note: Leap year is not taken into calculation!
According to my brief investigation according to the leap year it would be easier to extend the SQL query with tolerance of 1 day, ie to use - INTERVAL 8 DAY instead of 7 and then control the validity of the day outside the database during processing the data in a loop.
Yes, it is possible.
The function you are looking for is +/- INTERVAL expr unit. See MySQL Date and Time Functions
So to get 7 days back use - INTERVAL 7 DAY:
SELECT *
FROM tablename
WHERE DATE(timefield) BETWEEN '2017-12-14' - INTERVAL 7 DAY AND '2017-12-14'
According to your example would be enough to use -INTERVAL 1 WEEK:
SELECT *
FROM tablename
WHERE DATE(timefield) BETWEEN '2017-12-14' - INTERVAL 1 WEEK AND '2017-12-14'
And List of all possible units
MICROSECOND SECOND MINUTE HOUR DAY WEEK MONTH QUARTER YEAR
SECOND_MICROSECOND MINUTE_MICROSECOND MINUTE_SECOND HOUR_MICROSECOND
HOUR_SECOND HOUR_MINUTE DAY_MICROSECOND DAY_SECOND DAY_MINUTE DAY_HOUR
YEAR_MONTH
I have the following tables:
In other words I have a set of customers I follow throughout time. I have a column of the date of their first purchase, and another column with another purchase they made at another time.
I want to make a column which specifies the time period in which the specific purchase was made. The time periods should be defined such that a new period starts the 20th each month and the first period for each customer should therefore be the day they made their first purchase and until the 20th.
This is illustrated below:
What I need:
I have tried to implement this via a handful of if statements like:
WHEN DAY(c.created)<21 and DAY(s.created)<21 and year(c.created)-year(s.created)=0
THEN MONTH(c.created)-MONTH(s.created)+1
WHEN DAY(c.created)>20 and DAY(s.created)<21 and year(c.created)-year(s.created)=0
THEN MONTH(c.created)-MONTH(s.created)+2
and so on.
I want to know if there is an easy(er) and simple(r) way to handle this problem?
I work in MySQL Workbench 6.3 CE
The date of the first day of the calendar month in which a customer made a purchase can be found like this:
DATE_FORMAT(First_purchase , '%Y-%m-01')
So, the date of the first day of your fiscal month, which starts on the 20th of each calendar month, can be found like this.
DATE_FORMAT(First_purchase - INTERVAL 19 DAY, '%Y-%m-01') + INTERVAL 19 DAY
Then, you can use TIMESTAMPDIFF as follows to get the number of months between two of these sorts of numbers.
TIMESTAMPDIFF(
MONTH,
DATE_FORMAT(First_purchase - INTERVAL 19 DAY, '%Y-%m-01') + INTERVAL 19 DAY,
DATE_FORMAT(Date_created - INTERVAL 19 DAY, '%Y-%m-01') + INTERVAL 19 DAY) + 1
That will get you the number of the fiscal month, starting with First_purchase, in which Date_created is found, where the first fiscal month has the number 1.
Using native date arithmetic in place of DAY(), MONTH(), and YEAR() functions is much more likely to keep working over ends of years and in leap years and all that.
I have MySQL condition that grabs a time interval from now back x number of months. Typically, this will be set to 13 months so you can compare the current month to that of last year.
'created > DATE_SUB(now(), INTERVAL ' . $timeInterval . ' MONTH)'
So for example last January compared to this January, but I'd like to include all of the previous years month. So instead of January 20, 2015 to January 20, 2016 I would have January 01, 2015 to the current date in January this year until February 1st.
I'd use DATE_FORMAT to make it quick and easy, replace the "day" part of the date with a constant. Then subtract your number of months...
... t.created > DATE_FORMAT(NOW(),'%Y-%m-01') - INTERVAL ? MONTH
As a demonstration of what is returned by that expression, we can test it using a simple SELECT statement:
SELECT NOW(), DATE_FORMAT(NOW(),'%Y-%m-01') - INTERVAL 12 MONTH
NOW() DATE_FORMAT(NOW(),'%Y-%m-01') - INTERVAL 12 MONTH
------------------- -------------------------------------------------
2016-01-27 21:01:02 2015-01-01
FOLLOWUP
Are you sure you want a "greater than" comparison, rather than a "greater than or equal to" comparison >= ?
There are other approaches to generating that date value to compare to. You could use DATE(NOW()) or CURDATE() to return the current date with no time component.
And use the DAY() function to get the numeric value of the current day, and then subtract that (minus 1) as a number of days. For example, something like this:
>= DATE(NOW()) - INTERVAL DAY(NOW())-1 DAY - INTERVAL 12 MONTH
That seems messier and more complicated. I think it's easier to understand stuffing in the '-01' as the day part.
created > str_to_date(concat(year(now())-1, '-01-01'), '%Y-%m-%d')
Or if you need not all previous year:
select str_to_date(concat(year(now())-1, '-', month(now()),'-01'), '%Y-%m-%d')
For "2012-07-12", how can I get the start of the week, i.e., "2012-07-08", and start of the month, i.e., "2012-07-01"?
First day of the month:
SELECT DATE_FORMAT('2007-07-12', '%Y-%m-01');
output: 2007-07-01
First day of the week:
SELECT DATE_SUB('2007-07-12', INTERVAL DAYOFWEEK('2007-07-12')-1 DAY);
output: 2007-07-08
MySQL reference: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add
Same answer as Borophyll's, but I have changed the behavior of the first day of the month to return a date, not just a string which avoids date formatting/parsing mentioned in user151220's answer.
First day of the month:
SELECT DATE_SUB('2007-07-12', INTERVAL DAYOFMONTH('2007-07-12') - 1 DAY);
output: 2007-07-01
First day of the week:
SELECT DATE_SUB('2007-07-12', INTERVAL DAYOFWEEK('2007-07-12') - 1 DAY);
output: 2007-07-08
MySQL reference: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add
For those who need Monday as the first day of the week:
SELECT DATE_SUB('2007-07-12', INTERVAL WEEKDAY('2007-07-12') DAY);
output: 2007-07-09
This relies on the WEEKDAY function, which starts with Monday instead of DAYOFWEEK, which starts with Sunday.
The DATE_FORMAT reply from Borophyll is very good, but gives a string rather than a date. So can't be compared easily.
If you need to use this as a comparison to a date field, use str_to_date to reverse it back to date rather than string.
select x from y where date >= str_to_date( DATE_FORMAT(now()-interval 12 month,'Y-%m-01'), '%Y-%m-%d')
If you are (say) looking at 12 months sales figures, but you want to always start off from the 1st of a month.
This will work if you want to just code it and forget about it, it will use datetime now and always return MTD results-
where date_completed between date_sub(date(now()), INTERVAL dayofmonth(now()) -1 day) and now()
I've got an mysql-db with charges in it, with a datetime. Every month i want to create an invoice with all the charges from last month or earlier. So if it´s may 2nd, 5th or 30th 2012, i still only want the invoices from april 2012 or earlier. I've tried with date_sub, but it just subtracts a month, so it only invoices up to the same day of the previous month. How should i do this?
get * from Ads WHERE AdEnd > ??
Ty!
I always found that if you subtract the day of the month in days from the current date, you'll get the last day of the previous month. For example, on the 15th of the month, subtract 15 days, and you'll end up with the last day of the previous month:
SELECT (DATE_SUB(CURDATE(),INTERVAL DAYOFMONTH(CURDATE()) DAY))
If CURDATE() is 2012-05-05 then the above returns 2012-04-30.
So, to get Ads up to the last day of last month, do something like this:
SELECT *
FROM Ads
WHERE AdEnd <= (DATE_SUB(CURDATE(),INTERVAL DAYOFMONTH(CURDATE()) DAY))
This works if AdEnd is a DATE, but if it's a DATETIME, you'll just want to do less than the first of the month, so you subtract one less day to get the first of the month like this:
SELECT *
FROM Ads
WHERE AdEnd < (DATE_SUB(CURDATE(),INTERVAL DAYOFMONTH(CURDATE()) - 1 DAY))
Try date_diff, for example:
SELECT DATEDIFF('2008-11-30','2008-11-29') AS DiffDate
yields:
1