I have a page that shows posts stored in a mysql database. When the post is created the user can select how long they want the post to be visible for and I'm trying to figure how to only show posts for a determined duration. Here is some of my code (that hopefully shows the logic I'm trying).
//Query database
$sql = <<<SQL
SELECT *
FROM `posts`
SQL;
if(!$result = $db_connection->query($sql)){
die('There was an error running the query [' . $db_connection->error . ']');
}
while($row = $result->fetch_assoc()){
//The date the post was made
$date_of_post = $row['date_of_post'];
//The duration of the post in days eg 7.
$duration = $row['duration'];
//Attempting to add duration to date
$newdate = strtotime($duration, $date_of_post);
//Only show posts that are still valid, eg date + duration is less than today's date
if($newdate > now()){
echo '<h2>Post Title</h2>';
echo '<p>Date of Posted:'.$date.'</p>';
}
}
You can use a where clause and a date_add function to apply this filter directly in your SQL query. Simply add the duration days to the date_of_post value, and compare it against NOW().
Note that because you're storing your duration value as a varchar instead of an int, you'll need to convert the duration value to a signed int.
Here is an example, with the date_add expanded out to make it clearer to understand what is happening.
select
*
from
posts
where
date_add
(
date_of_post,
INTERVAL convert(duration, SIGNED INT) DAY
) > NOW()
As a side note, you should always try to filter your data in your query, and not in your PHP script. Don't just select your entire table into your script - let SQL do as much work as possible. The RDBMS is far more efficient than PHP, and you'll save a lot on overhead (eg amount of data sent over the network, and how much RAM has to be used to store the results for PHP to work with, etc).
Related
I am trying to piece together a bunch of steps and it is getting confusing.
I have a MySQL table with (MySQL) timestamp and runtime fields. I would like to make another table containing date and sum (runtime) fields.
I would like to execute a cron job every day after midnight to sum the runtimes from the day before and insert that with the date of the previous day.
I would like the cron job to make sure that the prior days were run, and if not, it would run those as well.
I am new to cron, so I don't know if that last step is necessary.
Here are my trouble points:
Writing a query that will convert timestamps to dates and sum each date.
Setting up a PHP cron job that will make sure all dates are entered but not double enter.
Here's the code I've tried on part 1 (I'm running on CURDATE until it works):
$result=mysql_query("SELECT SUM(runtime) AS value_today FROM `table` WHERE date = CURDATE()",$link)
$row = mysql_fetch_array($result);
echo $row[value_today];
instead of convert timestamp from query, why dont just set a variable using php by
$yesterday_date = date('Y-m-d', strtotime('-1 days'))
to get yesterday date
then query
SELECT SUM(runtime) AS total FROM db_table WHERE DATE(date_run) = '" . $yesterday_date . "' GROUP BY DATE(date_run)"
I am using HTML input type="date" to allow users to input appointment dates.
Now I want to query the database and show all appointments that are "today" and in the future.
Not dates that have already passed.
Here is my SQL Script
$today = date('d-m-Y');
$sql = "SELECT *
FROM `client1`
WHERE `client` = '$customer'
AND DATEDIFF('$today', `date`) >= 0
ORDER BY `id` DESC";
Can someone guide me as to how I can achieve this?
I have seen several directions online but I want to have the sorting done at the moment of query.
I have solved the issue!
My date() format was incorrect because HTML input type="date" inserts YYYY-MM-DD into the database =/
$today = date('d-m-Y');
should be
$today = date('Y-m-d');
My operator >= should have been <= to show today and future dates.
Thanks everyone for the help. I should have tried fixing it for 5 more minutes before posting.
Why are you using PHP to compare dates in the database? I assume its a date field so you can use MySQL to do it for you:
SELECT *
FROM `client1`
WHERE `client` = '$customer'
AND DATEDIFF(date_format(now(), '%Y/%m/%d'), `date`) >= 0
ORDER BY `id` DESC
None of the responses have specified sargable predicates. If you perform an operation on a column in the where clause, there is no discernible stopping point.
where ... some_function( some_field ) = some_constant_value ...
Even if some_field is indexed, a complete table scan must be performed because there is no way to know if the output of the operation is also ordered.
From my understanding the date column is in a sortable form -- either a date field or a string in lexically sortable format 'yyyy-mm-dd'. That being the case, don't do any operation on it.
where ... some_field >= now() ...
Thus the system can use the result of now() as a target value to find exactly where in the index to start looking. It knows it can ignore all the rows with indexed values "down" from the target value. It has to look only at rows with indexed values at or "up" from the target value. That is, it performs an index seek to the correct starting point and proceeds from there. This could mean totally bypassing many, many rows.
Or, to put it bluntly, ditch the datediff and do a direct comparison.
I am using PHP and MySQL for a very small CMS.
One of the functional requirements is that the system gives back the amount of days left before renewal date (For example how many days left between now and the renewal field in the database)
The process I was going to take was #3AM every morning, go through all the records (via PHP) and update the required field. The trick is that if this figure is <30 (days) then send email to ....who ever.
This seems very impracticable and as it would be in a loop maybe too intense on the database.
If I could have the database make this calculation it would be better (not sure how).
HOWEVER
I will still have to loop through all records anyway to see if there are <30 days before renewal (to send email).
If anyone has a better suggestion, i would be very grateful. Below is some presudo code I would like to do
$q = "SELECT * FROM testDB ";
$r = mysql_query($q);
while ( $a = mysql_fetch_assoc($r) ) {
$rnlDate= stripslashes($a['renewal_Date']); //get Date inserted in table
$thisId= stripslashes($a['id']); // current record id
$timeLeft=$rnlDate-date(); // get time left
if($timeLeft <=30)
{
$makeEmail= createEmail(field_ID); // not sure how to wait until this function completes
}
doUpdate($timeLeft);
function doUpdate($timeLeft)
{
"UPDATE INTO testDB WHERE 'id' =$thisId; VALUES('','$timeLeft',)";
}
obviously just passing the idea here, but any other soloutions are very welcome.
Cheers
Do this in your query. It's much easier:
$q = "SELECT *
FROM testDB
WHERE renewal_Date < CURRENT_TIMESTAMP - INTERVAL 30 DAY";
You can do this in MySQL using the TIMESTAMPDIFF() function, something like
SELECT TIMESTAMPDIFF(DAY,NOW(),column_name) AS diff
FROM table
WHERE id = 'whatever';
This will give you the number of days left, plug into a variable $days. Then
if(($days > 0) && ($days <30)) {
// do something
}
stripslashes? you really really really need to upgrade your php version. magic_quotes have been disabled by default for a long time now, and having it on is a sign of a badly misconfigured server, and/or badly out-of-date PHP install.
that being said, your query would not be "heavy" or "bad", unless you're dealing with billions of rows...
SELECT ...
FROM ...
WHERE renewal_date > (CURDATE() - INTERVAL 30 DAY) AND (renewal_date < CURDATE() )
should fetch all records where the renewal date falls within the past 30 days.
I have events in my MySQL database wich all have a date. When I perform a SQL query to get all the events in the future, I get an error... Although, the date of the events are in the future. When I change my SQL request to select dates in the past, I get those from the future...
The SQL statement below has worked before, but for some reason it stopped working...
I use this SQL request:
$sql = "SELECT * FROM calendar WHERE date >= CURDATE() order by `date`";
I get an empty array as result...
However if I change the query to this, I get all the events in my database:
$sql = "SELECT * FROM calendar WHERE date <= CURDATE() order by `date`";
This is my database data. In my opinion, all data are in the future...
The format of the date table is a default date-type:
When I ask my server about the time echo date("Y-m-d"); I get todays date as result...
So where do I make a mistake?
You may be checking the wrong date field. Do you have a created date as well as a scheduled date?
I could be crazy from the cold medicine I am on at the moment, but your date table can't possibly be the date of your calendar items, the id filed is only an int(2), that seems kind of small.
maybe something simplier? I notice the column name in your table is date, which also is the name of a function date() that returns the date part of a datetime value. If thats the case
$sql = "SELECT * FROM calendar c WHERE c.`date` <= CURDATE() order by `date`";
would do the trick. Even if not mysql itself, the gui app youre using (seems like phpmyadmin to me) might get confused.
(btw, you forgot the closing tick of date in the order by clause)
getting an empty set is meaning nothing is found matching. I would look at your formatting of your date. The only other thing i was thinking is that it is comparing an unmatched type so just returns an empty set.
use DATEDIFF :
DATEDIFF
WHERE DATEDIFF(date, CURDATE) > 0
Before you make your query, run this one:
SET time_zone = '-2:00'; // or whatever your time zone is.
Don't ask me how or why, but I've truncated my table and re-inserted some data and my query seems to work just fine:
$sql = "SELECT * FROM `calendar` WHERE `date` >= CURDATE() order by `date`";
So, despite the fact the problems seems to be solved by truncating my table, I would like to know the answer to the why-question... Anyone can provide me with it?
I need to keep a field in a data-base and update it with a time somehow, then later I need to check that time to see if it was over 30 minutes ago or not, and if not, how minutes left until 30?
I am going to be doing this with PHP+MySql can anyone tell me the simplest way to do this?
Thanks!!
Let's assume you want to know how long ago the last update/insert in the table occurred.
You can set up a table with a timestamp field with an on update clause
CREATE TABLE foo (
id int auto_increment,
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
primary key(id),
key(ts)
)
and then query the record with the largest value in ts
SELECT
TIMEDIFF(Now()-Interval 30 Minute, ts)
FROM
foo
ORDER BY
ts DESC
LIMIT
1
edit: This also works if you want to get all records that have been inserted/modified within e.g. the last 12 hours.
SELECT
TIMEDIFF(Now()-Interval 30 Minute, ts)
FROM
foo
WHERE
ts > Now()-Interval 12 hour
ORDER BY
ts DESC
edit2: there's also an off chance you might be interested in http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html:SHOW TABLE STATUS returns the following fields:
...
Update_time
When the data file was last updated. For some storage engines, this value is NULL. For example, InnoDB stores multiple tables in its tablespace and the data file timestamp does not apply. For MyISAM, the data file timestamp is used; however, on Windows the timestamp is not updated by updates so the value is inaccurate.
I could wrap all you insert and update MySql calls in a function something like the following:
function MySqlQuery($query, $res){
$result = mysql_query($qs, $res);
if($result === false){
mysql_query("QUERY STRING TO UPDATE FIELD IN DATABASE WITH NEW TIME", $res);
}
return $result;
}
Replace the "QUERY STRING TO UPDATE FIELD IN DATABASE WITH NEW TIME" with an actual update query and you should be good to go.
What I do is, put a Time Stamp on the latest record. Pull the latest record with a MySQL Query and then use the mysql fetch array function to get the time of that last record. This goes the same for using a database that is updated with the time only.
You would be able to manipulate that time with a function that compares the current time to the time on the record. From there you can display the time since last posting, and if it is over 30 minutes you can make it echo a message.
$currenttime = /* PHP Time Formatting you wish to use. */
$query = mysql_query("SELECT time FROM database");
$row = mysql_fetch_array($query);
echo "Last Record Posted #" . $row['time'];
$timesince = $currenttime - $row['time'];
echo "Time Since Last Post:" . $time - $row['time'];
if($timesince >= "30"){
echo "Over 30 Minutes!";
}
Let me know if you have any questions. The above code should give you an idea of how it would work, but it is a rough example.
Best of Luck!!
EDIT:::
Sorry, I misread the question, You would still need to enter the time into the database. You can still use the above code to pull the time and see if it is greater than 30 minutes or not.
For the Time Stamp check out the PHP Time Manual. You will want to pick the same time format for both the MySQL Input and the code I posted above.