This is little confusing me how to select dates from table on continuous basis.
Suppose i have absent_report table and have entries like this,
Sno Code date
1 101 01-01-2014
2 101 02-01-2014
3 101 03-01-2014
4 101 05-01-2014
5 101 06-01-2014
6 101 07-01-2014
I only want to select continues date from a date. like first three dates not fourth one and so on.
Example Like I have date from which I have to compare is Like 31-12-2013 now from here next continues dates like 01-01-2014,02-01-2014,03-01-2014 only, No matter next records like i have dates in that table 05-01-2014,06-01-2014,07-01-2014. I just want first continuous dates.Hope this clear more what I want.
Use the BETWEEN syntax
SELECT * FROM table WHERE date BETWEEN '2014-01-01' AND '2014-01-03';
You can check if either the next row has the following day or the previous row has the previous day. To do this, I used DATE_ADD() as described in this answer. However, I am not sure if this would be better than implementing the logic in PHP alltogether.
SELECT sno, code, date FROM table AS current
WHERE
DATE(DATE_ADD(date, INTERVAL -1 DAY)) = (SELECT date FROM table AS previous WHERE previous.date < current.date ORDER BY date DESC LIMIT 1)
OR
DATE(DATE_ADD(date, INTERVAL +1 DAY)) = (SELECT date FROM table AS next WHERE next.date > current.date ORDER BY date ASC LIMIT 1)
ORDER BY date ASC
See it work here.
Related
My following query shows the date and the count of the emails found on each day (last 2 days)
My problem is that if no emails are found today, the today date will not be displayed on the output. (if yesterday has emails, it will show only 1 row with yesterday date and email).
How can I edit my query to always show 2 rows, today and yesterday, date and number of emails even zero?
SELECT maildate,
COUNT(*) AS totalEmails
FROM emails
WHERE maildate >= Date_add(Curdate(), interval - 2 DAY)
AND company_id = 1
GROUP BY DATE(maildate)
ORDER BY maildate desc
There are many tricks to creating a list of dates (or numeric sequences similarly). The one I like to use with MySQL is using #sqlvariables. I will typically start with a baseline value such as your date -2 days. I will do a cross-join to any other table in the database that has at least as many records as you expect in your output... Say 30 days, or a whole year 366 days, or longer. The inner sql variable prep will keep increasing itself by whatever increment (you could even do date ranges such as begin/end of a week, month, etc). Now you have your table of all possible dates you are looking to fill.
Now, I do a secondary query by the value -- in this case your email date and apply the group by. Using the where clause in this query will make IT faster since it can utilize the date on its query result set before returning for the LEFT-JOIN to the date range result set.
Now, your simple left-join gets both parts of all dates to be included and those corresponding counts that do exist.
Note the table alias "AnyTableWithAtLeast3RecordInIt" in the "JustDates" query could in-fact be your "emails" table. Since we don't care about any criteria except a record exists, and we are applying a limit of 30 days in my example, it will be instantaneous.
select
JustDates.DateToInclude,
coalesce( SumCnts.TotalEmails, 0 ) TotalEmails
from
( select
#myDate := DATE_ADD( #myDate, INTERVAL 1 DAY ) as DateToInclude
from
( select #myDate := Date_add(Curdate(), interval - 2 DAY) ) as SQLVars,
AnyTableWithAtLeast3RecordInIt
limit 30 ) JustDates
left join
( select
maildate,
COUNT(*) AS totalEmails
FROM
emails
WHERE
maildate >= Date_add(Curdate(), interval - 2 DAY)
AND company_id = 1
GROUP BY
DATE(maildate) ) SumCnts
ON JustDates.DateToInclude = SumCnts.MailDate
Now, judging by your query, but unclarified request... Your emails table CAN HAVE FUTURE DATES? Is that correct? Such as a Dr. Office and appointments are for the future and you want to get emails out for a given range. This is what I was inferring and hence had my limit to only go out 30 days... If you need longer, just extend the LIMIT clause.
You need a table that contains all dates in the needed range. If its only about today and yesterday, you can easily create it as a subquery (derived table).
SELECT Curdate() as maildate
UNION ALL
SELECT Curdate() - INTERVAL 1 DAY
http://rextester.com/ALH50651
Now you can LEFT JOIN your table and count the rows:
SELECT sub.maildate,
COUNT(m.maildate) AS totalEmails
FROM (
SELECT Curdate() as maildate
UNION ALL
SELECT Curdate() - INTERVAL 1 DAY
) sub
LEFT JOIN emails m
ON DATE(m.maildate) = sub.maildate
AND m.company_id = 1
GROUP BY sub.maildate
ORDER BY sub.maildate desc
In MySql...
How to exclude today date ( upto 2.30PM on each day ) data row from MYSQL fetch array..
How to publish today result + last 3 using PHP + mysql ...
Sample Table : ALLRESULTDATA
id price date
1 Rs.50 2015-12-09
2 Rs.5 2015-12-10
3 Rs.52 2015-12-11
4 Rs.55 2015-12-12
5 Rs.53 2015-12-13
6 Rs.53 2015-12-14
How to fetch last 3 days result ( Exclude today result upto 2.30PM afterthat publish TODAY)
mysql_query("select * from ALLRESULTDATA desc limit 4");
Here's a query that will include the row for today and the rows for the last three days:
SELECT *
FROM ALLRESULTDATA
WHERE
`date` = CURDATE()
OR
`date` >= DATE_ADD(CURDATE(), INTERVAL -3 DAY)
ORDER BY `date` DESC
LIMIT 4
SQL Fiddle: http://sqlfiddle.com/#!9/88561/3
I think you also mean to only include the result for today if the time is after 14:30, that's probably possible but it would be clunky in MySQL in my opinion.
I think you would be better grabbing the current time in php and if it's greater, running the query above and if not, run a different query, e.g. :
SELECT *
FROM ALLRESULTDATA
WHERE
`date` != CURDATE()
AND
`date` >= DATE_ADD(CURDATE(), INTERVAL -3 DAY)
ORDER BY `date` DESC
LIMIT 3
i.e. change the first conditional operator to != and change the OR to an AND and then also change the LIMIT to 3.
Today Excluded Fiddle: http://sqlfiddle.com/#!9/88561/5
EDIT
I just noticed your comment saying that the dates are stored as a VARCHAR(10), if possible I'd recommend changing your schema so that the dates are stored as DATE.
An alternative is the STR_TO_DATE() function, but I don't think the performance will be particularly nice if you have to resort to using it.
I have the following code and query:
//$month is an array of datetime objects
foreach($month as $key => $indMonth){
$formattedMonth[] = $month[$key]->format('Y-m-d');
}
$formattedMonths = implode("','",$formattedMonth);
$query = "SELECT id,date FROM table WHERE date in ('$formattedMonths') ORDER by date DESC";
The database holds dates for the past 450 days, but it is imperfect and there are some missing days. The point of the script is to retrieve data from the current day of the month and then the corresponding day on the five previous months, but I need a failsafe for when a date happens to be missing.
How can I modify this query so it picks either the date in the "where in" portion of the query or it finds the date nearest to that particular date in the array?
Is this best to do in the query, or am I better off returning a more complete data set, then using PHP to find out if the date I want is available?
MySQL offers some decent date arithmetic. For example, if you have the date '2015-11-10' (10-Nov-2015) you can get the same day three months prior with this expression:
'2015-11-10` - INTERVAL 3 MONTH
That will kick back '2015-08-10', which is what you want.
This date arithmetic works predictably even with longer and shorter months, and with leap years. For example,
'2015-03-31' - INTERVAL 1 MONTH, '2016-03-31' - INTERVAL 1 MONTH
gives back '2015-02-28', '2016-02-29' as you might expect. And
'2015-03-31' - INTERVAL 2 MONTH, '2016-03-31' - INTERVAL 2 MONTH
gives back '2015-03-31', '2016-03-31'. Perfect.
Now, only you can decide whether this predictable behavior is correct for your application: only you know what you want to do with the previous five months of data, when the day in question is near the end of the month.
Let's assume it's correct and move on. Here is a subquery that can be used to generate a sequence of six dates, one day per month ending today.
SELECT CURDATE() - INTERVAL seq.seq MONTH day_of_month
FROM ( SELECT 0 AS seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 6) seq
We can use this little query as a subquery, and LEFT JOIN it to your data. That would work like this:
SELECT id, day_of_month
FROM (
SELECT CURDATE() - INTERVAL seq.seq MONTH day_of_month
FROM ( SELECT 0 AS seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 6) seq
) days
LEFT JOIN table ON table.date = days.day_of_month
This is a cool way to do it because you'll always get at least one row in the resultset for each date in the list, even if there's nothing matching in table.
The closest date gets a little hairier. It's possible to write a query like that. But MySQL lacks a WITH clause so the query is ridiculously repetitive.
I have MySQL query I can't solve and couldn't find solution by googling. I have table something like this:
recnr event date
1 event1 today-3
2 event2 today-2
3 event3 today
4 event4 today
5 event5 today+3
6 event6 today+7
I have to create query which will select 3 most recent events starting with today. I've tried with:
SELECT event FROM table
WHERE (date <= CURDATE()) recnr LIMIT 3;
but it selects first three events in the table. How to tell it to start with today and go backwards and not to start with first and go forward?
Use an order by statement?
SELECT event FROM table WHERE (date <= CURDATE()) ORDER BY date DESC LIMIT 3;
You need an order by clause in your query
Reference - order by
SELECT event FROM table WHERE (date <= CURDATE()) ORDER BY date DESC LIMIT 3 ;
Trying to get my head around, If I select a record such as WHERE item_id='$item_id' AND date(datetime)='2012-06-25' and if that record does not exist so I want to get the nearest-latest record after that date. How can I achieve that in a query?
All I can think of the only way right now is if num_of_rows is 0 then I add 3 days period ahead to that day and search again and get the DESC datetime LIMIT 1 (in case there are multiple rows). But who knows I can do it with just a query.
The record could have multiple rows in one day. So if a particular date has no record, how to get the next nearest available data given the same $item_id?
SELECT *
FROM table
WHERE field <= '2012-06-25'
ORDER BY field DESC
LIMIT 1
I think this is what you are looking for:
SELECT *
FROM my_table
WHERE datetime BETWEEN '2012-06-25 00:00:00' AND
DATE_ADD('2012-06-25 00:00:00', INTERVAL 3 DAY)
ORDER BY datetime ASC
LIMIT 1;
also create index on field datetime for faster performance.
This will bring back the item closest to the date that you enter into the query. It won't however look for before or after, just find the closest date to what you enter in.
select
min(abs(DATEDIFF(date(datetime),'2012-06-25'))) as minDiff
,yourID
from table1
group by yourID
order by 1 asc;