How to fetch current week data till today's date ?
Example - Current week start from 2017-08-01 to 2017-08-07 and today date is 2017-08-03. I want to fetch data from 2017-08-01 to 2017-08-03 using query.
This is query -
SELECT *
FROM user_data
WHERE YEARWEEK(`date`, 1) = YEARWEEK(CURDATE(), 1)
I have resolved my problem.
SELECT *
FROM current_week
WHERE YEARWEEK(`dt`, 1) = YEARWEEK(CURDATE(), 1) and dt <= curdate() order by dt
This is working fine.
This one gets tricky in the last and first weeks of calendar years.
First you need to decide whether your week starts on Sunday or Monday. That is based on your national jurisdiction's business practices. In North America, it's generally Sunday. In Europe it is sometimes Monday.
You need an expression that computes the first moment of a calendar week based on a date.
This is such an expression for weeks starting Sunday.
FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7))
This is it for weeks starting Monday. (Notice the -2.)
FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -2, 7))
Now you can select stuff from your table that's in the current week.
SELECT whatever, whatever
FROM user_data
WHERE `date` >= FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7))
If you want stuff from the week before the current week use this
SELECT whatever, whatever
FROM user_data
WHERE `date` >= FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7)) - INTERVAL 7 DAY
AND `date` < FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7))
Related
I'm building a MySQL report that could be run at any point in a given month. When run, it will need to pull through all results where the date of the record is in the month in 5 months' time - e.g. if run any time in December, it will need to pull through any records with a date between 1st May and 31st May 2020, if run in January it would pull through the June records and so on.
Have been searching for a few different date functions but can't seem to find the right one to let me look ahead 5 months using a date interval, but that will only show me from the 1st to the last day of that month.
Closest I seem to have is this (which my query doesn't like):
due_date <= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 6, -1) AND due_date >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 5, 0
Thanks
You can try below query to get that result -
SELECT adddate(current_date, interval 5 month) curr_date
,DATE_SUB(adddate(current_date, interval 5 month),INTERVAL DAYOFMONTH(adddate(current_date, interval 5 month))-1 DAY) AS '1st of month'
,last_day(adddate(now(), interval 5 month)) last_of_month;
Here is the fiddle.
I am trying to get average of a column player_count week-by-week over the past 6 weeks. But the problem is that I also want the start and the end of the week date which corresponds to a specific average.
What I have tried:
SELECT AVG(player_count) as average,
updated_at,
updated_at + INTERVAL WEEKDAY(updated_at) + 7 DAY as EndDate
FROM `gtan_servers`
WHERE server_short_name = 'FiveRP'
GROUP BY WEEK(updated_at)
ORDER BY updated_at DESC
LIMIT 6
The updated_at column is intended to be taken as start of the week and EndDate is going to be taken as end of the week in which a specific average of the player count is provided.
But this query is not working correctly regarding the week dates. I can fetch the average yes but the week dates are not being fetched correctly. Any help would be highly appreciated.
You need an expression that truncates an arbitrary date to the first day of the week in which it occurs. That is, it returns 2017-05-21 (Sunday) if you give it 2017-05-24
This expression does that, assuming your weeks start on Sundays. Here's an explanation.
FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -1, 7))
Then you need to use that as a GROUP BY expression and a WHERE expression.
SELECT AVG(player_count) as average,
FROM_DAYS(TO_DAYS(updated_at) -MOD(TO_DAYS(updated_at) -1, 7)) week_beginning,
FROM_DAYS(TO_DAYS(updated_at) -MOD(TO_DAYS(updated_at) -1, 7)) + INTERVAL 6 DAY week_ending
FROM `gtan_servers`
WHERE server_short_name = 'FiveRP'
AND updated_at >= FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) - INTERVAL 6 WEEK
GROUP BY FROM_DAYS(TO_DAYS(updated_at) -MOD(TO_DAYS(updated_at) -1, 7))
ORDER BY 2 DESC
LIMIT 6
The WHERE automatically filters out records from your table that are too old for your report.
This query gets a little repetitive, but it works nicely.
You could create a stored function like this:
DELIMITER $$
DROP FUNCTION IF EXISTS TRUNC_SUNDAY$$
CREATE
FUNCTION TRUNC_SUNDAY(datestamp DATETIME)
RETURNS DATE DETERMINISTIC NO SQL
COMMENT 'returns preceding Sunday'
RETURN FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -1, 7))$$
DELIMITER ;
Then your query becomes more readable:
SELECT AVG(player_count) as average,
TRUNC_SUNDAY(updated_at) week_beginning,
TRUNC_SUNDAY(updated_at) + INTERVAL 6 DAY week_ending
FROM `gtan_servers`
WHERE server_short_name = 'FiveRP'
AND updated_at >= TRUNC_SUNDAY(NOW()) - INTERVAL 6 WEEK
GROUP BY TRUNC_SUNDAY(updated_at)
ORDER BY TRUNC_SUNDAY(updated_at) DESC
LIMIT 6
If your weeks start on Mondays change the -1 to a -2.
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')
I need to display two calculated columns of the sum of GP for one week and in the other column previous
I think my way is right but i am missing something
I am trying to get my result to be like this::
|WEEK|JP|AUS|GB|
|PREV|22|32|23|
|CUR|12|15|12|
my sql is this I believe I may need to pivot the data
SELECT
(SUM(`GP`), `gptw`)
FROM
(SELECT
`GP`,
`Country`
FROM
`Finance`
WHERE DATE >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE()) + 6 DAY
AND DATE < CURDATE() - INTERVAL DAYOFWEEK(CURDATE()) - 1 DAY
GROUP BY `Country`) AS lastweeek
INNER JOIN
(SELECT
SUM(`GP`) AS `gptw`,
`Country`
FROM
Finance
WHERE DATEDIFF(NOW(), `date`) < 4
GROUP BY `Country`) AS `thisweek`
Nitpick: DATE is a poor choice of column name because it's a reserved SQL word.
There are four levels of logic here.
First, you need to have working logic to figure out which week each day is in.
Second, you need to select the correct range of DATE values.
Third, you need to get the GROUP BY logic right.
Fourth, you need to pivot your result set to get this week and last week into the same row. This pivoting should be the subject of another question.
First, this expression will turn any DATETIME value into the preceding Sunday.
FROM_DAYS(TO_DAYS(value) -MOD(TO_DAYS(value) -1, 7))
Second, here's what you need to select two weeks (last week and this week)
WHERE `DATE` >= FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) - INTERVAL 7 DAY
AND `DATE` < FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) + INTERVAL 7 DAY
This gets the range of dates starting with the Sunday before last Sunday, and ending the moment before the Sunday after this Sunday, a two week range.
Third, you need to group correctly. In your schema, group by week and by country. It would go something like this:
SELECT SUM(`GP`) AS GP,
`Country`,
FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7)) AS week_beginning
FROM `Finance`
WHERE `DATE` >= FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) - INTERVAL 7 DAY
AND `DATE` < FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) + INTERVAL 7 DAY
GROUP BY `Country`, FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7))
ORDER BY `Country`, FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7))
This will give you two rows per country, one for the week_beginning a week ago, and one for the current week. This could do the trick for you. If not, you can pivot this query's results to arrange the rows the way you want them. That should be the subject of another question.
Finally, if you can define stored functions in your MySQL instance, you should define the function TRUNC_SUNDAY. Then you can write your query more readably like this:
SELECT SUM(`GP`) AS GP,
`Country`,
TRUNC_SUNDAY(`DATE`) AS week_beginning
FROM `Finance`
WHERE `DATE` >= TRUNC_SUNDAY(NOW()) - INTERVAL 7 DAY
AND `DATE` < TRUNC_SUNDAY(NOW()) + INTERVAL 7 DAY
GROUP BY `Country`, TRUNC_SUNDAY(`DATE`)
ORDER BY `Country`, TRUNC_SUNDAY(`DATE`)
Here is SQL code to define the stored TRUNC_SUNDAY function you need:
DELIMITER $$
DROP FUNCTION IF EXISTS `TRUNC_SUNDAY`$$
CREATE FUNCTION `TRUNC_SUNDAY`(datestamp DATETIME)
RETURNS DATE
NO SQL
DETERMINISTIC
COMMENT 'returns preceding Sunday'
RETURN FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -1, 7))$$
DELIMITER ;
You can find a detailed writeup of this technique, including a TRUNC_MONDAY function, here. You'll need the TRUNC_MONDAY function if your weekdays are defined as starting on Monday rather than Sunday. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/
Suppose I have 2011-01-03 and I want to get the first of the week, which is sunday, which is 2011-01-02, how do I go about doing that?
The reason is I have this query:
select
YEAR(date_entered) as year,
date(date_entered) as week, <-------This is what I want to change to select the first day of the week.
SUM(1) as total_ncrs,
SUM(case when orgin = picked_up_at then 1 else 0 end) as ncrs_caught_at_station
from sugarcrm2.ncr_ncr
where
sugarcrm2.ncr_ncr.date_entered > date('2011-01-01')
and orgin in(
'Silkscreen',
'Brake',
'Assembly',
'Welding',
'Machining',
'2000W Laser',
'Paint Booth 1',
'Paint Prep',
'Packaging',
'PEM',
'Deburr',
'Laser ',
'Paint Booth 2',
'Toolpath'
)
and date_entered is not null
and orgin is not null
AND(grading = 'Minor' or grading = 'Major')
and week(date_entered) > week(current_timestamp) -20
group by year, week(date_entered)
order by year asc, week asc
And yes, I realize that origin is spelled wrong but it was here before I was so I can't correct it as too many internal apps reference it.
So, I am grouping by weeks but I want this to populate my chart, so I can't have all the beginning of weeks looking like different dates. How do I fix this?
If the week starts on Sunday do this:
DATE_ADD(mydate, INTERVAL(1-DAYOFWEEK(mydate)) DAY)
If the week starts on Monday do this:
DATE_ADD(mydate, INTERVAL(-WEEKDAY(mydate)) DAY);
more info
If you need to handle weeks which start on Mondays, you could also do it that way. First define a custom FIRST_DAY_OF_WEEK function:
DELIMITER ;;
CREATE FUNCTION FIRST_DAY_OF_WEEK(day DATE)
RETURNS DATE DETERMINISTIC
BEGIN
RETURN SUBDATE(day, WEEKDAY(day));
END;;
DELIMITER ;
And then you could do:
SELECT FIRST_DAY_OF_WEEK('2011-01-03');
For your information, MySQL provides two different functions to retrieve the first day of a week. There is DAYOFWEEK:
Returns the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday). These index values correspond to the ODBC standard.
And WEEKDAY:
Returns the weekday index for date (0 = Monday, 1 = Tuesday, … 6 = Sunday).
If week starts on Monday
SELECT SUBDATE(mydate, weekday(mydate));
If week starts on Sunday
SELECT SUBDATE(mydate, dayofweek(mydate) - 1);
Example:
SELECT SUBDATE('2018-04-11', weekday('2018-04-11'));
2018-04-09
SELECT SUBDATE('2018-04-11', dayofweek('2018-04-11') - 1);
2018-04-08
Week starts day from sunday then get First date of the Week and Last date of week
SELECT
DATE("2019-03-31" + INTERVAL (1 - DAYOFWEEK("2019-03-31")) DAY) as start_date,
DATE("2019-03-31" + INTERVAL (7 - DAYOFWEEK("2019-03-31")) DAY) as end_date
Week starts day from Monday then get First date of the Week and Last date of week
SELECT
DATE("2019-03-31" + INTERVAL ( - WEEKDAY("2019-03-31")) DAY) as start_date,
DATE("2019-03-31" + INTERVAL (6 - WEEKDAY("2019-03-31")) DAY) as end_date
select '2011-01-03' - INTERVAL (WEEKDAY('2011-01-03')+1) DAY;
returns the date of the first day of week. You may look into it.
This is a much simpler approach than writing a function to determine the first day of a week.
Some variants would be such as
SELECT DATE_ADD((SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE())+1)DAY),INTERVAL 7 DAY) (for the ending date of a query, such as between "beginning date" and "ending date").
SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE())+1) DAY (for the beginning date of a query).
This will return all values for the current week. An example query would be as follows:
SELECT b.foo FROM bar b
WHERE b.datefield BETWEEN
(SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE())+1) DAY)
AND (SELECT DATE_ADD((SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE())+1)DAY),INTERVAL 7 DAY))
This works form me
Just make sure both dates in the below query are the same...
SELECT ('2017-10-07' - INTERVAL WEEKDAY('2017-10-07') Day) As `mondaythisweek`
This query returns: 2017-10-02 which is a monday,
But if your first day is sunday, then just subtract a day from the result of this and wallah!
If the week starts on Monday do this:
DATE_SUB(mydate, INTERVAL WEEKDAY(mydate) DAY)
SELECT MIN(DATE*given_date*) FROM *table_name*
This will return when the week started at for any given date.
Keep the good work going!