get the nearest date mysql - php

I have the following dates in my table. How do I find a closest date from either today (if today's date is there) or if today's date is not there then the nearest past date?
2012-10-01 aa123
2012-10-02 aa43
2012-10-03 aa478
2012-10-04 aa40
2012-10-05 aa54
2012-10-06 de34
2012-10-07 a5434
2012-10-08 r4t
2012-10-09 x34
2012-10-10 q23
2012-10-11 b53
So if today is '2012-10-07' is then the record will be a5434. But if 2012-10-07 is missing then the record will be de34 which belongs to 2012-10-06 since that would be the closest past day from today.
I am not sure where to start on this one, so I haven't tried anything yet. Need a sql solution to this.

It's simple, just get one of the last date <= the current date:
$now = date("Y-m-d");
$sql = "SELECT * FROM date_table where date_field <= '$now' ORDER BY date_field DESC LIMIT 1 OFFSET 1";

Add an ORDER BY statement to the query. The following will order the rows by their date, with the latest at the top and oldest at the bottom.
SELECT `id`, `date` FROM `table` ORDER BY `date` DESC LIMIT 1;

Related

Get max value of given date range and group by day PHP MYSQL

I am having so much trouble with this. I am trying to get the maximum value per day given the range. But I keep getting a blank value in my count column when I load the query result.
<?php
include("dbconnect.php");
$link=Connection();
$data1 = '2016-04-29 00:00:00';
$data2 = '2016-05-02 00:00:00';
$result = mysql_query(
"
SELECT DATE(orderDate), MAX(Count)
FROM testLocation
WHERE orderDate
BETWEEN '$data1%' AND '$data2%'
GROUP BY DATE(orderDate)
"
,$link
);
?>
A few things to look at here.
First, the % signs in your date constants should not be there. Those only work with the LIKE operator.
Second, the BETWEEN operator works poorly for DATETIME values, because it is the equivalent of this:
WHERE orderDate >= '$data1'
AND orderDate <= '$data2' -- wrong!
This excludes everything after precisely midnight on the ending date. <= is the wrong comparison to use for DATETIME.
You should use this instead:
WHERE orderDate >= '$data1'
AND orderDate < '$data2' + INTERVAL 1 DAY
It includes everything up until, but not including, < midnight on the day after the end date you gave. That means it will include everything on the last day of your date range, which is presumably what you want.
Third, I suggest you give alias column names to the columns in your result set. That will make them easier for php code to retrieve.
SELECT DATE(orderDate) orderDate,
MAX(Count) maxCount
FROM testLocation
WHERE orderDate >= '$data1'
AND orderDate < '$data2' + INTERVAL 1 DAY
GROUP BY DATE(orderDate)
Fourth, if your testLocation table has no records in it at all for a particular date, the result set from this query will omit that date.
Fifth (others mentioned this in comments) the mysql_ API is not a good choice for your php programming; it's insecure.
I suggest you to please use PDO for the above queries.Your question is not fully clear but if you intend to retrieve database result whose value is maximum you can do the following way.
$sql='SELECT * FROM testLocation
WHERE orderDate
BETWEEN '$data1%' AND '$data2%' ORDER BY orderDate
DESC LIMIT 1';
By this query we have limited the retrieved data to be 1 and that is why you will get only the maximum value here and mark we have ordered the data in descending manner.

Select a MySQL record that hasn't been used before or past a certain date

I am trying to select 3 random records from a MySQL db where the lastUsedDate (the date the record was last updated) is beyond a set time period or NULL.
My logic is this:
If the lastUsedDate is NULL, then this record could be selected.
If the lastUsedDate is 7 days or more older than the current date,
it is a candidate to be randomly selected.
I want to ignore dates that are 7 days and younger.
I know Rand() is slow, but this table only has 30 records.
SELECT * FROM myTable
WHERE lastUsedDate <= DATE_SUB(CURDATE() ,INTERVAL 7 DAY) OR lastUsedDate IS NULL
ORDER BY RAND()
LIMIT 3
Eventually, after 30 days, the lastUsedDate will no longer be NULL as all 30 will be used up. This is why I want to recycle rows after 7 days.
Anyone point me in the right direction?
Try
SELECT * FROM myTable
WHERE IFNULL(lastUsedDate, '0000-00-00') <= DATE_SUB(CURDATE() ,INTERVAL 7 DAY)
ORDER BY RAND()
LIMIT 3
Since you tagged this as PHP I'm guessing you are running this query inside PHP, in which case why not simplify the query and do more in php
$date_limit = date("Y-m-d", strtotime("-7 days", time()));
$sql = "SELECT * FROM myTable WHERE IFNULL(lastUsedDate, '0000-00-00') <= '$date_limit' ORDER BY RAND() LIMIT 3";
good luck

Average day values of last month as a SQL statement

I got a table with two columns, timestamp (like '1405184196') and value.
I've saved some measured values.
$day= time()-84600;
$result = mysql_query('SELECT timestamp, value FROM table WHERE timestamp >= "'.$day.'" ORDER BY timestamp ASC');
This is how I get all values for the last 24h.
But is it possible to get average day values for the last month with a SQL statement or do I have to select all values of the last month and calculate the average of each day via PHP?
Several issues with Anish's answer:
1) This won't work if date+time is being stored in the timestamp field.
2) It assumes the OP means last month i.e June, May etc and not the last say 30 days.
This solves those issues:
SELECT DATE(`timestamp`) as `timestamp`, AVG(value)
FROM table
WHERE `timestamp` >= CURDATE() - INTERVAL 1 MONTH
GROUP BY DATE(`timestamp)
EDIT
Since the timestamp is a unix timestamp and the OP would like a calendar month:
SELECT DATE(FROM_UNIX(`timestamp`)) as `timestamp`, AVG(value)
FROM table
WHERE MONTH(FROM_UNIX(`timestamp`)) = MONTH(NOW() - 1)
GROUP BY DATE(FROM_UNIX(`timestamp))
You can do this:-
SELECT timestamp, AVG(value)
FROM table
GROUP BY timestamp
HAVING MONTH(timestamp) = MONTH(NOW()) - 1;
This query calculates average for last month.
DEMO

MySQL - Select the least day of the current week, not necessarily the first day of the week

Using PHP/MySQL
I'm trying to create a select statement that gets the data from the least day of the current week (I'm using it to show data on a certain player 'this week'). The week starts on Sunday. Sundays's data may not always exist therefore if the Sunday data isn't found then it would use the next earliest day found, Monday, Tuesday, etc.
My date column is named 'theDate' and the datatype is 'DATE'
The query would need to be something like:
SELECT *
FROM table_name
WHERE name = '$username'
AND [...theDate = earliest day of data found for the current week week]
LIMIT 1
It would return a single row of data.
This is a query I tried for getting the 'this week' data, It doesn't seem to work correctly on Sunday's it shows nothing:
SELECT *
FROM table_name
WHERE playerName = '$username'
AND YEARWEEK(theDate) = YEARWEEK(CURRENT_DATE)
ORDER BY theDate;
This is the query that I'm using to get 'this months' data and it works even if the first day of the months data is not found, it will use the earliest date of data found in the current month/year (this query works perfect for me):
SELECT *
FROM table_name
WHERE playerName = '$username'
AND theDate >= CAST( DATE_FORMAT( NOW(),'%Y-%m-01') AS DATE)
ORDER BY theDate
LIMIT 1
Without trying this, you probably need an inner query:
select *
from table_name tn
where tn.the_date =
(select min(the_date)
from table_name
where WEEKOFYEAR(the_date) = WEEKOFYEAR(CURDATE())
and YEAR(the_date) = YEAR(CURDATE()))
viz, give me the row(s) in the table with a date equal to the earliest date in the table in the current week and year.
Try this
SELECT * FROM table_name WHERE name = '$username'
AND your_data IS NOT NULL
AND WEEK(the_date,0 = WEEK(NOW(),0))
ORDER BY DATE_FORMAT(the_date,'%w') ASC
Try the following, replace YOUR_DATE with the date from the column you want (theDate):
SELECT ADDDATE(YOUR_DATE, INTERVAL 1-DAYOFWEEK(YOUR_DATE) DAY)
FirstDay from dual
Did you try:
SELECT ADDDATE(theDate , INTERVAL 1-DAYOFWEEK(theDate ) DAY) FirstDay
FROM table_name
WHERE playerName = '$username'
ORDER BY theDate DESC
LIMIT 1

SQL Query Concerning Dates

I have the following relation in my schema:
Entries:
entryId(PK) auto_inc
date date
In order to count the total entries in the relation I use a query in my php like this:
$sql = mysql_query("SELECT COUNT(*) as Frequency FROM Entries WHERE date = '$date'");
My question is how can I count the number of entries for the CURRENT month..
You want a between query based on your date column.
WHERE date BETWEEN startdate AND enddate.
Between is equivalent to date >= startdate AND date <= enddate. It would of course be also possible to just use >= AND < explicitly which would simplify it a bit because you don't need to find the last day of the month, but just the first day of the following month using only DATE_ADD(..., INTERVAL 1 MONTH).
However startdate and enddate in this case would be derived from CURDATE().
You can use CURDATE(), MONTH(), DATE_ADD and STR_TO_DATE to derive the dates you need (1st day of current month, last day of current month). This article solves a similar problem and all the techniques needed are shown in examples that you should be able to adapt:
http://www.gizmola.com/blog/archives/107-Calculate-a-persons-age-in-a-MySQL-query.html
The first day of the current month is obvious YEAR-MONTH(CURDATE())-01. The last day you can calculate by using DATE_ADD to add 1 Month to the first day of the current month, then DATE_ADD -1 Days.
update-
Ok, I went and formulated the full query. Don't think str_to_date is really needed to get the index efficiency but didn't actually check.
SELECT count(*)
FROM entries
WHERE `date` BETWEEN
CONCAT(YEAR(CURDATE()), '-', MONTH(CURDATE()), '-', '01')
AND
DATE_ADD(DATE_ADD(CONCAT(YEAR(CURDATE()), '-', MONTH(CURDATE()), '-', '01'), INTERVAL 1 MONTH), INTERVAL -1 DAY);
Try this
SELECT COUNT(1) AS `Frequency`
FROM `Entries`
WHERE EXTRACT(YEAR_MONTH FROM `date`) = EXTRACT(YEAR_MONTH FROM CURDATE())
See EXTRACT() and CURDATE()
Edit: Changed NOW() to CURDATE() as it is more appropriate here
Try
$sql = mysql_query("SELECT COUNT(*) as Frequency FROM Entries WHERE MONTH(date) = MONTH(NOW()) );

Categories