I have a date column in my MySQL database. How do I get dayofquarter from this date?
I have been doing a datediff from the start of the quarter up till now, but would like to be able to do this dynamically.
You've got to do some calculation, but it can definitely be done dynamicly in MySQL alone. I'll use the date April 30, 2016 (2016-04-30) as in the example:
First, here is how you dynamically get the first day of a quarter:
SELECT makedate(YEAR("2016-04-30"), 1) + INTERVAL QUARTER("2016-04-30") QUARTER - INTERVAL 1 QUARTER
Once you have this, subtract it from the original date to get the day of quarter for the date and add 1 to it (or the first day would be day 0)
SELECT DATEDIFF("2016-04-30",(makedate( YEAR ("2016-04-30"), 1) + INTERVAL QUARTER("2016-04-30") QUARTER - INTERVAL 1 QUARTER)) + 1 AS dayofquarter
To be dynamic, replace all three 2016-04-30 dates with the date column in the table you're querying from:
SELECT DATEDIFF(`somedatecolumn`,(makedate( YEAR (`somedatecolumn`), 1) + INTERVAL QUARTER(`somedatecolumn`) QUARTER - INTERVAL 1 QUARTER)) + 1 AS dayofquarter FROM `my_table`
If you're looking for a simple, snazzy, built-in function like DAYOFQUARTER(somedate), your out of luck, you'll need to create your own http://dev.mysql.com/doc/refman/5.7/en/create-procedure.html
Related
id start_date interval period
1 2018-01-22 2 month
2 2018-02-25 3 week
3 2017-11-24 3 day
4 2017-07-22 1 year
5 2018-02-25 2 week
the above is my table data sample. start_dates will be expired based on interval and period(i.e id-1 will have due date after 2 months from the start_date, id-2 will have due after 3 weeks vice versa). period is enum of (day,week,month,year). requirement is, Client can give any period of dates. let's say 25-06-2026 to 13-07-2026 like that.. I have to return the ids whose due dates falls under that period.I hope i made my question clear.
I am using mysql 5.7. I found a way to achieve this with recursive CTE's.(not available in mysql 5.7). and there is a way to achieve this by populating virtual records by using inline sub queries along with unions but its a performance killer and we can't do populate virtual records every time a client request comes.(like given in the link Generating a series of dates) I have reached a point to get results for a single date which is very easy. Below is my query.
SELECT b.*
FROM (SELECT a.*,
CASE
WHEN period = 'week' THEN MOD(Datediff('2018-07-22', start_date), 7 * intervals)
WHEN period = 'month'
AND Day('2018-07-22') = Day(start_date)
AND MOD(Period_diff(201807, Extract(YEAR_MONTH FROM start_date)), intervals) = 0 THEN 0
WHEN period = 'year'
AND Day('2018-07-22') = Day(start_date)
AND MOD(Period_diff(201807, Extract(
YEAR_MONTH FROM start_date)) / 12,
intervals) = 0 THEN 0
WHEN period = 'day' THEN MOD(Datediff('2018-07-22', start_date) , intervals)
end filters
FROM kml_subs a)b
WHERE b.filters = 0;
But I need to do this for a period of dates not a single date. Any suggestions or solutions will be much appreciated.
My desired result shoud be like..
if i give two dates.say 2030-05-21 & 2030-05-27. due dates falls under those 6 dates between(2030-05-21 & 2030-05-27) will be shown in the result.
id
1
4
My question is different from Using DATE_ADD with a Column Name as the Interval Value . I am expecting a dynamic way to check due dates based on start_date
Thanks, Kannan
In MySQL, it would seem that a query along these lines would suffice. (Almost) everything else could and should be handled in application level code...
SELECT *
, CASE my_period WHEN 'day' THEN start_date + INTERVAL my_interval DAY
WHEN 'week' THEN start_date + INTERVAL my_interval WEEK
WHEN 'month' THEN start_date + INTERVAL my_interval MONTH
WHEN 'year' THEN start_date + INTERVAL my_interval YEAR
END due_date
FROM my_table;
Wracking my brain trying to figure this out, and I can't seem to find any existing threads that help.
Simply, I'd like to find the first day of the week (as a date) but one year ago, for any given date. Our calendar week starts on Sunday.
Here's a snap of the table I have at my disposal
Any help is greatly appreciated!
Thanks!
See this. How do I get the first day of the week of a date in mysql?
You can get your required result this way:
mydate - INTERVAL 1 YEAR + INTERVAL 1-DAYOFWEEK(mydate - INTERVAL 1 YEAR) DAY
Explanation:
mydate - INTERVAL 1 YEAR
gives you the date a year before mydate.
anyday + INTERVAL 1-DAYOFWEEK(anyday) DAY
gives you the Sunday beginning the week of anyday.
Similarly you can get the first day of the month of anyday like this:
LAST_DAY(anyday) + INTERVAL 1 DAY - INTERVAL 1 MONTH
Some people call this week- and month- truncation.
You can use datesub() to subtract one year from today (curdate()). Get the weekday with weekday(). It returns a number from 0 to 6 where 0 is Monday. Subtract that many days plus one, as your first weekday is Sunday not Monday.
date_sub(date_sub(curdate(),
INTERVAL 1 YEAR),
INTERVAL weekday(date_sub(curdate(),
INTERVAL 1 YEAR)) + 1 DAY)
Here's a function to do it:
CREATE FUNCTION `SUNDAY`(indate date) RETURNS date
NO SQL
BEGIN
declare prevyear date;
set prevyear = indate - interval 1 year;
return prevyear - weekday(prevyear) - interval 1 day;
END
How would I go about writing a statement in MySQL to return the previous start and end date of the previous quarter? Say if I wanted the start and end date of the quarter before this one (i.e. beginning of last October and end of last December).
Try this one:
SELECT
MAKEDATE(YEAR(CURDATE()), 1) + INTERVAL QUARTER(CURDATE())-1 QUARTER - INTERVAL 1 DAY,
MAKEDATE(YEAR(CURDATE()), 1) + INTERVAL QUARTER(CURDATE())-2 QUARTER
I find it helpful to use this TRUNC_QUARTER stored function. It converts any date or date/time value into midnight on the first day of the calendar quarter in which it occurs. Then you can use INTERVAL arithmetic to manipulate it.
DELIMITER $$
DROP FUNCTION IF EXISTS TRUNC_QUARTER$$
CREATE
FUNCTION TRUNC_QUARTER(datestamp DATETIME)
RETURNS DATE DETERMINISTIC NO SQL
COMMENT 'returns preceding first of the quarter'
RETURN DATE(CONCAT(YEAR(datestamp),'-', 1 + 3*(QUARTER(datestamp)-1),'-01'))$$
DELIMITER ;
With it you can write:
SELECT TRUNC_QUARTER(CURDATE()) - INTERVAL 1 QUARTER start_last_quarter,
TRUNC_QUARTER(CURDATE()) - INTERVAL 1 DAY end_last_quarter
Begin and end of quarters are fixed, so there is no need to actually “calculate” those – we know they are January 1st, April 1st, etc, and March 31st, June 30th, etc. respectively.
So all that leaves us with is to get the correct year prepended to those fixed dates – if the current quarter is Q1, then go back one year, else use the current year.
QUARTER(NOW()) will give us the current quarter (from 1 to 4), so this could be as simple as this:
SELECT
CASE QUARTER(NOW())
WHEN 1 THEN DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y-10-01')
WHEN 2 THEN DATE_FORMAT(NOW(), '%Y-01-01')
WHEN 3 THEN DATE_FORMAT(NOW(), '%Y-04-01')
WHEN 4 THEN DATE_FORMAT(NOW(), '%Y-07-01')
END AS previous_quarter_begin,
CASE QUARTER(NOW())
WHEN 1 THEN DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y-12-31')
WHEN 2 THEN DATE_FORMAT(NOW(), '%Y-03-31')
WHEN 3 THEN DATE_FORMAT(NOW(), '%Y-06-30')
WHEN 4 THEN DATE_FORMAT(NOW(), '%Y-09-30')
END AS previous_quarter_end
http://sqlfiddle.com/#!9/9eecb/1858
If you want those dates in a different format, say mm/dd/yyyy instead, then you can simply change the format specified to 10/01/%Y etc.
(And if you want to test this, to see if it actually works correctly for different dates, then you can replace each occurrence of NOW() in the above query with a fixed date, like say '2015-12-22' to see if this will give the expected result for a date in December.)
This will work such that if the date is in the first quarter, it'll roll back to the previous year in quarter 4.
SELECT #dateLastQuarter := DATE_SUB('yourdate', INTERVAL 3 MONTH);
SELECT MAKEDATE(YEAR(#dateLastQuarter), 1) + INTERVAL QUARTER(#dateLastQuarter) QUARTER - INTERVAL 1 QUARTER,
MAKEDATE(YEAR(#dateLastQuarter), 1) + INTERVAL QUARTER(#dateLastQuarter) QUARTER - INTERVAL 1 DAY;
I am trying to check for all records that occurred last month using the following statement.
Select * from statistics
where statistics_date
BETWEEN date_format(NOW() - INTERVAL 1 MONTH, '%Y-%m-01')
AND last_day(NOW() - INTERVAL 1 MONTH )
However, the selection does not include the last day. What I want is from the first second of the month until the last second of the month.
BETWEEN is notoriously bad for date and timestamp work because it gets the end date wrong.
Here's what you need:
First, let's compute the first day of the present month. You had that exactly right.
DATE_FORMAT(NOW(),'%Y-%m-01')
Next, let's compute the first day of last month:
DATE_FORMAT(NOW(),'%Y-%m-01') - INTERVAL 1 MONTH
Now, we select the records that lie in the interval.
Select *
from statistics
where statistics_date >= DATE_FORMAT(NOW(),'%Y-%m-01') - INTERVAL 1 MONTH
and statistics_date < DATE_FORMAT(NOW(),'%Y-%m-01')
Do you see how the beginning of the date range is chosen with >= and the end with <? Do you see how I used the first day of the present month for the end of the date range? Those things are important, because timestamps can have days and times in them. Consider the timestamp '2013-01-31 23:58'. It happens to be after '2012-01-31' so between won't catch it.
where MONTH(statistics_date) = MONTH(NOW()) - 1
How do I do something like the following
SELECT ADDDATE(t_invoice.last_bill_date, INTERVAL t_invoice.interval t_invoice.interval_unit)
FROM t_invoice
...where the column t_invoice.last_bill_date is a date, t_invoice.interval is an integer and t_invoice.interval_unit is a string.
What I like about the ADDDATE() function is that if I write a
SELECT ADDDATE('2010-01-31', INTERVAL 1 MONTH)
It conveniently returns the last day of February - 2010-02-28. So it knows that 1 MONTH means 28 days for Feb (29 on leap year), 31 if odd number month, 30 if even number month. I would like to preserve this feature in my query.
Basically, I want to determine a person's next bill date based on his desired billing frequency. Is there a better way to achieve this?
SELECT t_invoice.last_bill_date + INTERVAL
CASE t_invoice.interval_unit
WHEN 'minute' THEN t_invoice.interval
WHEN 'hour' THEN t_invoice.interval*60
WHEN // etc...
END MINUTE as col1
FROM t_invoice
OR
SELECT
CASE t_invoice.interval_unit
WHEN 'minute' THEN t_invoice.last_bill_date + INTERVAL t_invoice.interval MINUTE
WHEN 'hour' THEN t_invoice.last_bill_date + INTERVAL t_invoice.interval HOUR
WHEN // etc...
END as col1
FROM t_invoice