Display only future database records with MySQL - php

I am trying to display only records two weeks in advance from the current date onwards. starttime is stored as a datetime data type in the database.
I have this,
SELECT id, date_format(starttime, '%d-%m-%Y %H:%i') AS formatted_start, date_format(starttime, '%Y-%m-%d') AS formatted_date,
date_format(endtime, ' %H:%i') AS formatted_end
FROM timedates WHERE user_id = 1 AND `status`='' AND YEARWEEK(formatted_date, 0) IN (YEARWEEK(NOW(), 0),
YEARWEEK(DATE_ADD(NOW(), INTERVAL 2 WEEK), 0))
But I am getting a syntax error YEARWEEK(formatted_date, 0) IN (YEARWEEK(NOW(), 0) AND YEARWEEK(DATE_ADD(NOW()
Could anyone tell me what's wrong with it?

It seems MySQL does not support calculated column in the where clause:
try
SELECT id, date_format(starttime, '%d-%m-%Y %H:%i') AS formatted_start,
date_format(starttime, '%Y-%m-%d') AS formatted_date,
date_format(endtime, ' %H:%i') AS formatted_end
FROM timedates
WHERE user_id = 1 AND `status`='' AND
YEARWEEK(starttime, 0) IN (
YEARWEEK(DATE_ADD(NOW(), INTERVAL 1 WEEK), 0),
YEARWEEK(DATE_ADD(NOW(), INTERVAL 2 WEEK), 0))
use starttime instead of formatted_date

As I said, I see no reason to use YEARWEEK function. You need start date set to today which is CURDATE() and plus 2 weeks period which is DATE_ADD(CURDATE(), INTERVAL 2 WEEK) and then we just check if starttime between those 2 dates.
SELECT id, date_format(starttime, '%d-%m-%Y %H:%i') AS formatted_start,
date_format(starttime, '%Y-%m-%d') AS formatted_date,
date_format(endtime, ' %H:%i') AS formatted_end
FROM timedates
WHERE user_id = 1
AND `status`=''
AND DATE(starttime) BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 2 WEEK)

How do you define "two weeks in advance"? Our normal inclination, is to think "within two weeks", which would be to simply before 14 days from now.
WHERE starttime >= NOW()
AND starttime < NOW() + INTERVAL 14 DAY
But the original query is using YEARWEEK function, and the behavior with that is a bit different.
If today is Thursday, May 21, 1015. What is the range of dates that starttime should fall into?
For datetimes right now or in the future, we can just do:
WHERE starttime >= NOW()
(We can do just a > rather than >= if we want to exclude startime values that are an exact match for NOW().
The question is, the bit about "two weeks in advance". Adding 14 days, or 2 weeks, would get us up to Thursday, June 4, 2015. It looks like you might also want to include Friday and Saturday, June 5th and 6th. (Up until Sunday, June th.)
We can use an expression to return "Sunday on or following 14 days from today"
If it's a Sunday, we just use that date. (For convenience, we think of that as adding 0 days). If it's Saturday, we need to add 1 day. If it's a Friday, add 2 days, ... Monday, add 6 days.
Conveniently, the expression 6 - WEEKDAY(NOW()) gives us the number of days we need to add to today's date to get to the next Sunday.
Reference: https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_weekday
We probably want to lop the time off at midnight, we can use the DATE() function to do that.
-- startime values on or after now and before midnight
-- of the first sunday on or after the date two weeks from now
WHERE starttime >= NOW()
AND starttime < DATE(NOW()) + INTERVAL 14+6-WEEKDAY(NOW()) DAY
It's much easier to read and understand what the query is doing when we reference bare columns from the table on one side, and do the gyration and manipulation on the other side. It's also easier to test. And, maybe more importantly, it allows MySQL to make effective use of an "range scan" operation on a suitable index, rather than having to evaluate a function on every row in the table.
If today is '2015-05-21', and what you meant by "two weeks in advance" was up until the second Sunday from now (Sunday, May 31, 2015... 1 week and 3 days from now) just replace the 14 with 7.
Again, it really depends on how you define "two weeks in advance", how you determine what that ending date boundary is. Once you can define that, you can write an expression that returns the value, and just compare to value stored in the starttime column.

Related

Ranking query from the last x months

I want to get all records from the last x months from my MySQL server. Using 2 months for example(Not from last 2 months, like last 60 days, but from the entire past month and so on. If actual month is april, I want all records from february and march).
I've tried some queries and the last one is
SELECT id FROM ranking WHERE (end_date BETWEEN DATE_FORMAT(NOW(), '%Y-%m-01') AND DATE_FORMAT(LAST_DAY(NOW() - INTERVAL 2 MONTH), '%Y-%m-%d'))
"end_date" is my date column which is a DATE column "2017-04-07".
That query above just returns nothing and I cant figure out where is the error.
Try this:
SELECT id
FROM ranking
WHERE end_date BETWEEN
DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 3 MONTH)) INTERVAL 1 DAY)
AND LAST_DAY(DATE_SUB(NOW(), INTERVAL 1 MONTH));
It calculates dates as like this:
For start date in range, it subtracts 3 months from current date, gets the last day of that month and adds a day in it to get the first day of next month (1st February in our case)
For end date, it subtracts one month from current date and gets the last day of that month (31st March in our case)
Try without convert it to string, And BETWEEN requires min date first.
SELECT id
FROM ranking
WHERE end_date BETWEEN LAST_DAY(CAST(NOW() as date) - INTERVAL 2 MONTH
AND CAST(NOW() as date)

MySQL query yearweek of the current week to start on a Thursday, end on Wednesday

I have a SQL statement set up to grab data from the current calendar week. By default, this grabs data starting on Sunday and ending on Saturday. I was hoping to change this so that the start of the calendar week is Thursday and it ends on Wednesday. Below is my statement:
SELECT *
FROM transactions
WHERE yearweek(transactionDate) = yearweek(now())
ORDER BY transactionDate DESC
Is there a way to modify the yearweek in a way to allow this?
Thanks!
You can take advantage of WEEKDAY() which returns a number representing the day of the week (0 = Monday, 6 = Sunday) and some straightforward maths to rewrite this query.
Subtract the weekday you want the week to start on (in your case 4 = Thursday) from the selected date, add 7 and take the remainder from 7. This will give you the number of days to subtract to get the start of your range.
A similar logic applies to calculate the end date of the range.
SELECT *
FROM transactions
WHERE DATE(transactionDate)
BETWEEN DATE_SUB(DATE(NOW()), INTERVAL (WEEKDAY(NOW()) - 4 + 7) % 7 DAY)
AND DATE_ADD(DATE(NOW()), INTERVAL 6 - (WEEKDAY(NOW()) - 4 + 7) % 7 DAY)
ORDER BY transactionDate DESC;
For a different starting date, substitute the weekday for 4 in the query.
You can specify start day - default is 0 (Sunday).
Just set it to 4 (Thursday):
YEARWEEK(transactionDate, 4)

Return the count of rows grouped by week MySQL

I am trying to get the row count from a MySQL table where the data is grouped by WEEK.
So far the query I have is:
"SELECT count(*) as tweets, twitTimeExtracted as date
FROM scene.twitData
group by week(twitTimeExtracted)"
This query returns the data below:
As you can see, the weeks are not correct, I'm expecting data for each week starting with Monday 7th January (7,14,21,28,4,11 etc...) and running through to this week.
I also tried a modified version of the orignal query:
SELECT count(*) as tweets, twitTimeExtracted as date
FROM scene.twitData
WHERE date(twitTimeExtracted)
BETWEEN '2013-01-07' and '2013-03-11'
group by week(twitTimeExtracted)
This returns similar results as the first query.
Maybe there is an inconsistency with some data stored in the DATETIME: twitTimeExtracted column on a few rows of data? I don't really know I'm not very experienced with MySQL.
Any help would really be appreciated.
Thanks
This converts the datetime value to the appropriate Monday of the week
select count(*) as tweets,
str_to_date(concat(yearweek(twitTimeExtracted), ' monday'), '%X%V %W') as `date`
from twitData
group by yearweek(twitTimeExtracted)
yearweek returns both week and year. Together with the string monday, str_to_date gives you the Monday's datetime value.
If your week starts on Monday, use yearweek(twitTimeExtracted, 1) instead.
One option to always get the Monday of the week is to use adddate:
SELECT count(*) as tweets, adddate(twitTimeExtracted, INTERVAL 2-DAYOFWEEK(twitTimeExtracted) DAY)
FROM twitData
WHERE date(twitTimeExtracted)
BETWEEN '2013-01-07' and '2013-03-11'
GROUP BY adddate(twitTimeExtracted, INTERVAL 2-DAYOFWEEK(twitTimeExtracted) DAY)
SQL Fiddle Demo
try this:
SELECT count(*) as tweets,
date_add('7 Jan 2012', day, datediff('7 Jan 2012', twitTimeExtracted)) % 7
FROM scene.twitData
group by date_add('7 Jan 2012', day, datediff('7 Jan 2012', twitTimeExtracted)) % 7
An alternate solution:
SELECT DATE(DATE_SUB(yourDate, INTERVAL WEEKDAY(yourDate) DAY));
Eg:
SELECT DATE(DATE_SUB(DATE("2016-04-11"), INTERVAL WEEKDAY(DATE("2016-04-11")) DAY));
You can also try this.
select
DATE_ADD(DATE(date), INTERVAL (7 - DAYOFWEEK(date)) DAY) as weekend,
count(tweets)
from scene.twitData
group by weekend;

mysql date show results today/yesterday/week

I am retrieving data from a table and show the total SUM of entries. What I want to do is to show the total SUM of entries made on today's date, yesterday and this month. The table is using the unix timestamp format (e.g. 1351771856 for example).
Currently I am using this line to show todays results:
AND comment_date > UNIX_TIMESTAMP() - 24 * 3600";
but that gives me just the entries for the last 24 hours.
Example: So let's say its Friday, 17:00 PM - it gives me the count from Thursday 17:00 PM to Friday 17:00 PM
What I want is to get the results for
Thursday 00:00:00 - 23:59:59 (yesterday in this case)
the results for today (00:00:00 - 23:59:59)
and last week, results that start on Monday, 00:00:00 until "today" (in this case Friday).
I couldn't find a way in the MySQL documentation to achieve this.
This mysql code should work for you:
// Today
AND DATE(from_unixtime(comment_date)) = CURRENT_DATE
// Yesterday
AND DATE(from_unixtime(comment_date)) = DATE_SUB(CURRENT_DATE,INTERVAL 1 DAY)
// This week
AND YEARWEEK(from_unixtime(comment_date), 1) = YEARWEEK(CURRENT_DATE, 1)
// This month
AND YEAR(from_unixtime(comment_date)) = YEAR(CURRENT_DATE)
AND MONTH(from_unixtime(comment_date)) = MONTH(CURRENT_DATE)
Simply use this:
AND comment_date > date_sub(current_date, interval 1 day)
See my answer here, I think it's quite related.
Pull records from orders table for the current week
Consider getting intimate with MySQL's GROUP BY. You will most likely need to know this if you use MySQL.

php mysql search birthday between two dates

I need to find the birth day of people from the table .. coming in next 7 days from today.
I have a query ..SELECT * FROMtableWHEREdobLIKE BETWEEN %-08-17 AND %-08-24 but it returns the records whose dates are not submitted in database..i mean the entry is 0000-00-00
I have stored the birthdates in dates format in table. Please Help me finding the bug.
Since this is mysql, I don't know if DATE_FORMAT() can work on this. But give this a try.
SELECT * FROM users WHERE DATE_FORMAT(dob, '%c-%d')
BETWEEN DATE_FORMAT('1983-08-17', '%c-%d')
AND DATE_FORMAT('1983-08-24', '%c-%d') OR (MONTH('1983-08-17') > MONTH('1983-08-24')
AND (MONTH(dob) >= MONTH('1983-08-17')
OR MONTH(dob) <= MONTH('1983-08-24')))
any year can be used (just to complete the date format) since year does not matter
UPDATE 1
Tested it on SQLFiddle.com
SQLFiddle Demo
UPDATE 2
I'm sorry for my first answer. I honestly missed to read this line coming in next 7 days from today. And I think that was the reason why I was downvoted by Imre L. He has his point. The reason why I posted the answer like that was because I thought the OP was asking for the days in between regardless of the year. So here is the update.
SELECT ....
FROM ....
WHERE DATE(dob) BETWEEN NOW() AND NOW() + INTERVAL 7 DAY
Hope it's clear now. :D
this will handle correctly cases wen there is a month or year change between the date range:
select *
from people
where (DAYOFYEAR(dob)+IF(DAYOFYEAR(CURDATE())>DAYOFYEAR(dob),1000,0))
between DAYOFYEAR(CURDATE())
and (DAYOFYEAR(CURDATE() + INTERVAL 7 DAY)+IF(DAYOFYEAR(CURDATE())>DAYOFYEAR(CURDATE() + INTERVAL 7 DAY),1000,0))
By converting the dob date into this year's date you can avoid issues where the period crosses a month or year boundary. This selects all rows where the birthdate occurs in the coming week:
SELECT * FROM users
WHERE concat( year(now()), mid(dob,5,6) )
BETWEEN now() AND date_add(now(), interval 7 day)
SELECT
str_to_date(DATE_ADD(dob, INTERVAL (YEAR(CURRENT_DATE()) - YEAR(dob)) YEAR), '%Y-%m-%d') BIRTHDAY,A.*
FROM app_membership A
WHERE str_to_date(DATE_ADD(dob, INTERVAL (YEAR(CURRENT_DATE()) - YEAR(dob)) YEAR), '%Y-%m-%d')
BETWEEN str_to_date('15-10-2017','%d-%m-%Y') and str_to_date('10-11-2017','%d-%m-%Y')
ORDER BY BIRTHDAY ASC;
Try this. Worked for me.
Lets list people who born in any month/year between december 14 and august 24. We know its an year before another one. We must count with months in the previous year. It's complex because you may have a problem comparing the month of the starting date with the month of the ending date. However, it may be solved with this query:
SELECT * FROM t_users WHERE (DATE_FORMAT(d_birth, '%m-%d')
BETWEEN DATE_FORMAT('2017-12-14', '%m-%d') AND
DATE_FORMAT('2018-08-24', '%m-%d'))
OR(MONTH('2017-12-31') >= MONTH('2018-08-24')
AND (MONTH(d_birth) >= MONTH('2017-12-31')
OR MONTH(d_birth) <= MONTH('2018-08-24')))

Categories