I am struggling with one thing. I'm trying to calculate how many days ago a certain date was, by using SQL. The dates I have in my database can be in two formats:
Aug 28 2014, 17:17:34 CEST
Dec 29 2015, 01:03:14 CET
Those are two examples of different dates. Notice the "CET" and "CEST".
But anyways, how would I go ahead and calculate this in a SQL query? I managed to do this in PHP but I'd like to do this in the SQL query itself (if possible). Because it would save up on a lot of memory usage. I try make my work as fast as possible. I want to only access data from users that has only logged in the past 2-3 days or so. Of course I could make a SELECT * FROM users and then run PHP to check for the dates. But is there perhaps a way to do this in SQL? Like: SELECT * FROM users WHERE [lastlogin < 2 days]
Here is my current PHP code. I'd really want to do this in SQL. By the way, my columns are currently in text. Datetime does not work with that format for some reason.
$lastlogin = $row['lastlogin'];
$lastlogin = str_replace("\xc2\xa0",' ',$lastlogin);
$Date = $lastlogin;
$Date = substr($Date, 0, strpos($Date, " CE"));
$now = date('Y-m-d');
$datetime1 = new DateTime($Date);
$datetime2 = new DateTime($now);
$interval = $datetime1->diff($datetime2);
$difference = $interval->format('%a days ago');
echo "Last login was: " . $difference;
you should alter your table to clean up the data. convert the data to two columns with the timezone info in one column and the date and time in another column.
you can split the data easily using SUBSTRING_INDEX() and convert the string to datetime at the same time.
split on the "C" of "CET" and "CEST" like this:
SELECT SUBSTRING_INDEX("Aug 28 2014, 17:17:34 CEST","C",1)
and you will see you are left with the date and time part only, albeit still in a string format. That can be changed with STR_TO_DATE and you can do both on the fly.
First add the new columns to store the data:
ALTER yourtablename ADD newdatecolumn DATETIME AFTER oldcolumnname;
ALTER yourtablename ADD newtimezonecolumn VARCHAR(4) AFTER newdatecolumn;
UPDATE yourtablename
SET newdatecolumn =
STR_TO_DATE(SUBSTRING_INDEX(olddatecolumn,"C",1), '%b %d %Y, %T')
you can then use SUBSTRING_INEX again, this time splitting on the last space in the column and grabbing the timezone for the other new column
UPDATE yourtablename
SET newtimezonecolumn = SUBSTRING_INDEX(olddatecolumn," ",-1)
then you will have data that you can work with more easily to use the suggested DATEDIFF() or other time and date functions. You can drop your old date column if you need to.
Note that yourtablename etc should be changed for actual table and column names.
You can use to_days() or datediff() functions
http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
Related
I have a table called reports in MySQL(MariaDB) . There is a one(out of 5) column named logdate which is is of type datetime .columns stores the the date and time (in 24hr format) .
for ex here is sample value from that column
2021-04-10 09:35:00
I have to find all reports between a given date and time .
I get 4 variables from form data in PHP
$fromdate= $_POST['fromdate'];
$todate= $_POST['todate'];
$fromtime= $_POST['fromtime'];
$totime= $_POST['totime'];
$fromtime and $totime are just integers with value from 0-23 for hours.
For example the condition may be like get all data between 4th April 2021
from 5 o'clock To 8 April 2021 18 o'clock
i.e. From 2021-04-04 03:00:00 to 2021-04-08 18:00:00. There will be never condition on minutes and seconds .
My question is how to construct a datetime in PHP compatible with MySQL types so I can have good(efficient, there are millions of records in table ) search speed?
for ex
$select = "select * from reports where logdate between ? and ? ";
P.S: I tried saving date and time as integer as unixtime stamp. But when i convert from and to date received using strttotime() I facing time format issue due to bug in my code which so can use datetime only.
If you have any suggestion to improve efficiency of DB please suggest.Thanks
Hi this link may be of help in optimizing date comparison
MySQL SELECT WHERE datetime matches day (and not necessarily time)
This one below, will help you in formatting your strtotime() by using strptime()
https://www.php.net/manual/en/function.strptime.php
Also check your spelling or typo; you wrote "strttotime()" instead of "strtotime()" yours has an extra 't' in str"tto"time, it should be str"to"time, though without the double qoutes
Though I can't say for sure this is the most effective way but you can use hour(logdate) to compare with $fromdate and $todate
$select = "select * from reports where hour(logdate) between ? and ? ";
But it will only compare hour part. Please mention how you are getting date part to compare?
It is not a good idea to make a calculation on a field in the WHERE CLAUSE. In this case MySQL / MariaDB must calculate the value from this field to comapare it to see
if this ROW has this condition. So MySQL must read the whole table FULL TABLE SCAN and CANT use any INDEX.
A better way to do this is to store the calculation on fix site. Then MySQL calculated it only one time and can use a Index ( if there one) .
you can easy use a query like this:
$select = "SELECT * FROM reports where logdate between date(?) + INTERVAL ? HOUR AND date(?) + INTERVAL ? HOUR ";
to test see:
SELECT date('2021-04-05') + INTERVAL 16 HOUR;
result:
2021-04-05 16:00:00
Here is what is working for me after using Bernds solution .
I constructing datetime string in php
$fromstr ="$fromdate"." "."$fromtime".":00:00";
$tostr="$todate"." "."$totime".":00:00";
here is my query looks like for date of 7th April to 10th April
$ select = "SELECT * FROM reports where logdate >= '$fromstr' and logdate <= '$tostr' order by logdate";
after echoing it
"SELECT * FROM reports where logdate >= '2021-04-07 3:00:00' and logdate <= '2021-04-10 5:00:00' order by logdate";```
However I am not sure if can use index for logdate column and utilize it with above query.
I need some advise on implementing my database schema properly. I have a cron script whose main functions are to Parse HTML docs => Create a DB tbl => Insert Records
I am used to run this script only once per month but I need to do it more frequently which means my database tables will increase significantly. At the moment my tables follow this format : table_03 where the last two digits represent the current month.
Now I am considering using PHP time() function to replace the current month.
My first question, is this a good way to approach it ?
My second issue is how do you go about creating a dynamic SELECT statement that fetches the last two tables in a Database based on their date ? or could be better to know if there is an MySQL query that does this job instead of relying of the table names ?
e.g
table_29_03 // 29 March
table_26_03 // 26 Mar...
table_25_03
...
My query should return the difference between the last two or three table, but not having consistent dates ( as monthly ) I am not sure how to do it.
At the moment I am doing the following :
$thisMonth = 'table_'.date('m');
$PrevMonth = 'table_'.date('m', strtotime('first day of last month'));
// find new records in this table not available in previous one
$sql = "
SELECT * FROM `".$thisMonth."` WHERE `".$thisMonth."`.`id`
NOT IN (
SELECT `".$PrevMonth."`.`id`
FROM `".$PrevMonth."`
WHERE `".$thisMonth."`.`id` = `".$PrevMonth."`.`id`
); ";
My second issue is how do you go about creating a dynamic SELECT statement that fetches the last two tables in a Database based on their date ?
is this what you want to achieve in MySQL?
SELECT create_time,table_name
FROM INFORMATION_SCHEMA.TABLES
ORDER BY create_time DESC LIMIT 2
you can add additional filters like what schema should we extract the data from, etc...
As for your first question, I am using gmdate as of now to extract the month and year of time.
$now = time();
$month = gmdate("m", $now);
$year = gmdate("y", $now);
gmdate: time returned is in Greenwich Mean Time (GMT).
using time(); to set your month is alright and i can see no problem in that.
Side Note: If you are running PHP and MySQL on separate machines, there would be some discrepancies in time if the datetime of those two are not synced. if you want an accurate time representation of both. You should be dependent on one machine.
If you want PHP to handle time logging, you can include a column in in your tables like 'created_at' which indicates the time when it was generated, based on PHP time();
If you want MySQL to handle it, you can query first the current date
select curdate();
then create the table names based on the month you fetched from your query.
I have a table that contains expiry dates for software modules. They are stored as type varchar(32). The database also stores dates one month prior to expiry and one day prior to expiry. When a license is approaching expiry the client is notified by message stack when they go into site admin.
What i want is to be able to edit the expiry date so that additional months or even years can be added to a clients license. The issue is that it also needs to update the other dates relative to the new expiry or they will get warnings when they shouldn't.
So field 'edate' contains a date stored as 25-10-2015, 'wdate' contains 25-09-2014 and 'fwdate' contains 24-10-2015
How do you take the date stored in the db and make it usable with code as seen below which originally calculated the dates.
$todays_date = strtotime("now");
$delta_eleven = strtotime("+11 months");
$delta_364 = strtotime("+1 year -1 day");
$delta_year = strtotime("+1 year");
$idate = date("d-m-Y", $todays_date);
$wdate= date("d-m-Y", $delta_eleven);
$fwdate = date("d-m-Y", $delta_364);
$edate = date("d-m-Y", $delta_year);
On database side you can use STR_TO_DATE(). Explanation of the second parameter can be found here. In your case
SELECT STR_TO_DATE(your_date_column, '%d-%m-%Y') FROM your_table;
To add or subtract something you can use
SELECT STR_TO_DATE(your_date_column, '%d-%m-%Y') + INTERVAL 11 MONTH
FROM your_table;
or
SELECT STR_TO_DATE(your_date_column, '%d-%m-%Y') + INTERVAL 1 YEAR - INTERVAL 1 DAY
FROM your_table;
It would be best if you added a column with the appropriate datatype (date, datetime or timestamp), update the new column with the str_to_date() function and then drop the old varchar column containing your dates. This makes work much easier and you can use indexes on the column if necessary.
I am using PHP and mysql and using either Date or DateTime to save dates in mysql database. On site I have been displaying dates the way they are saved in database.
But now I want to show dates EVERYWHERE on site using one format:
April 17 2013
or
April 17 2013 12:20:50
I know I can use date and strtotime functions to display dates in above format. However there are a lot of places where I have date displaying code. So I am looking to automate the process where my current code works and displays dates in above format.
Any idea of how mysql trigger or some php magic could be created that converts all dates run through SELECT query automatically without changing my sql or php code since I have a lot of places in my code and it would be overkill to change code at all places?
For Example:
Date Saved in DB: 2013-04-16 12:41:26
SELECT QUERY: SELECT * FROM myTable
PHP: echo $row->dated; displays 2013-04-16 12:41:26
I want that without changing my php code, dates should be shown in above mentioned format globally on whole site.
Any ideas please how it could be achieved ?
You can directly format in via query using DATE_FORMAT()
SELECT DATE_FORMAT(myDate, '%M %d %Y %h:%i') myDate
FROM TableName
SQLFiddle Demo
and echo in your PHP: $row->myDate
MySQL Trigger doesn't project values and It is only fired during CrUD operations.
I would like to suggest you an alternative approach which i love to use.
You should use the epoch time. An epoch time is basicly the number of second that has passed since 1 January 1970
One if the benefits i love is that it is very easy to calculate
differences in time since you are just dealing with number of
seconds and not a complicated format such as sec min hrs
Another benefit is that it is very easy to store since its a
integer so you can store it in a sql db and have your php code understand it without worrying about the format and things like that.
In php, if you use the time() function, it will return the epoch time.
And if you ever want to display it in a user friendly way. you can use the following code:
$epoch = time();
$dt = new DateTime("$epoch"); // convert UNIX timestamp to PHP DateTime
echo $dt->format('Y-m-d H:i:s'); // output = 2012-08-15 00:00:00
As you can see, the format of the date is very flexible and thus easy to use.
A nice example to find the date 1 week ago:
$epoch = time() - 604800; //604800 seconds = 7 days
$dt = new DateTime("$epoch"); // convert UNIX timestamp to PHP DateTime
echo $dt->format('Y-m-d H:i:s'); // output = 2012-08-15 00:00:00
Like many people, I am totally confused by the many date functions in PHP and MySQL. What I need is a to be able to store a date in MySQL and be able to view it on the screen in a human readable format, search on it by month, year, or combination of both using a standard web form, or sort it on months or years.
Example search would be all the records for febuary for the past 5 years.
I have a javascript calendar that inputs the month in the form as 02-12-2011.
What is the best format to use for this. What should the field be in MySQL.
Thanks
Please make use of the DateTime object.
Store the dates in mysql as a DATE format.
When writing the data
$date = new DateTime($_POST['date']);
or
$date = DateTime::createFromFormat('d-m-Y', $_POST['date']);
$query = sprintf("INSERT INTO `data` SET `date` = '%s'", $date->format('Y-m-d'))
When reading the data out create a DateTime object.
$date = new DateTime($row['date']);
Then you can print it in whatever format you want, e.g. You javascript's format:
echo $date->format('d-m-Y');
See
http://www.php.net/manual/en/class.datetime.php
and for date formats:
http://www.php.net/manual/en/function.date.php
As far as searches go, you can use mysql Date functions on the fields.
For all records in February for the last 5 years.
SELECT * FROM `data` WHERE MONTH(`date`) = 2 AND YEAR(`date`) >= YEAR(NOW()) - 5
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
The column type in MySQL should be date.
it's a date, so store it as a DATE column. You can either use UNIX_TIMESTAMP() in your SQL query or strtotime in PHP, to convert this back to a value that can be passed in to the php date() function, to output whatever format date you'd like.