Below are the table I've created and its records:
CREATE TABLE students (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
gender TEXT NOT NULL,
created_at datetime
);
INSERT INTO students VALUES (1, 'Ryan', 'M', '2012-11-03 00:00:00');
INSERT INTO students VALUES (2, 'Joanna', 'F', '2013-11-03 00:00:00');
To fetch the records by time, I use the following SQL statement:
SELECT * FROM students WHERE created_at > 1620489600000;
and both records can be returned, which confuses me because 1620489600000 (Sat May 08 2021 16:00:00 GMT+0000) should be a timestamp way later than the create_at fields of both records.
Indeed I know this can also be achieved by specifying a time formatted as 2012-11-03 00:00:00, but I just wonder:
whether we can effectively query a datetime column in where clause with unix timestamp?
if not, why does the above select statement return both records?
To compare two different data types MySQL automatically converts one of them to the other. In this case it tries to make numbers of the dates. What is the result? See here
The date gets converted to
20121103000000
which is bigger than
1620489600000
So the result in your WHERE clause is true and returns all records.
If you need to go from a Unix Timestamp you could use this:
WHERE created_at > FROM_UNIXTIME(1620489600000 / 1000)
Notice that I divided by 1000 because Unix time has to be in seconds and not milli seconds.
Related
I am creating and filling a MySQL table with the following Queries:
SET time_zone = '+00:00';
CREATE TABLE timestamp_n_datetime (
id INT,
time DATETIME,
avg_time DATETIME
);
INSERT INTO timestamp_n_datetime(id,time,avg_time)
VALUES("1","2023-01-03 10:12:13", NULL),
("1", "2023-02-04 11:13:14", NULL),
("2", "2023-03-02 09:14:10", NULL),
("2", "2023-04-02 05:15:50", NULL),
("1", "2023-06-10 02:04:10", NULL);
I want to fill the 'avg_time' column with the average of 'time' column grouped by the id. For example the first row has 'id' = 1 so the 'avg_time' column should take the average of first, second and fifth row since their 'id' is also 1.
How could I approach this question?
Edit: For clarification I want all the DATETIME columns to be converted to miliseconds, adding all of them up and then dividing by the number added. For example For id=2 converting them to miliseconds adding them up and then dividing by 2 (because there are two rows with 'id' = 2) gives the average of March 17, 2023 5:45:00 PM. I want to get an average this way.
Using This UNIX_TIMESTAMP to convert to seconds, then FROM_UNIXTIME to get it back to datetime format, this is how you can get the average :
select id, FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(`time`)))
from timestamp_n_datetime
group by id;
This is how to fill the average :
update timestamp_n_datetime td
inner join (
select id, FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(`time`))) as average
from timestamp_n_datetime
group by id
) as s on s.id = td.id
set avg_time = s.average;
My database has data imputed every 1 minute and is stored in the format 2020-04-05 16:20:04 under a column called timestamp.
I need a MySQL query to select data from every day at a specific hour (the second does not matter), for for example I want to get the data from 16:00 of every day from the past 30 days.
It currently, just grabs the data from the past 30 days and then the PHP application sorts it, however, this is causing very slow loading time, hence wanting to only select the wanted data from the database.
Example of data
Please try the following sql:
select
d.timestamp, hour(d.timestamp)
from
demo1 d
where
DATEDIFF(NOW(), d.timestamp) < 30 and hour(d.timestamp) = 16;
The create sql is as following:
CREATE TABLE `demo1` (
`id` int(11) not null auto_increment primary key,
`serverid` int(11) not null,
`timestamp` datetime not null,
KEY `idx_timestamp` (`timestamp`)
) engine = InnoDB;
insert into `demo1` (serverid, timestamp)
VALUES (1, "2020-07-05 16:20:04"),
(2, "2020-07-06 17:20:04"),
(3, "2020-07-07 16:40:04"),
(4, "2020-07-08 08:20:04"),
(5, "2020-07-05 15:20:04"),
(5, "2020-07-05 16:59:04"),
(5, "2020-06-04 16:59:04");
Zhiyong's response will work, but wont perform well. You need to figure out a way to get the query to use indexes.
You can add a simple index on timestamp and run the query this way:
SELECT
d.timestamp, d.*
FROM demo1 d
WHERE 1
AND d.timestamp > CURDATE() - INTERVAL 30 DAY
AND hour(d.timestamp) = 16;
In MySQL 5.7 and up, you can created a generated column (also called calculated column) top store the hour of the timestamp in a separate column. You can then index this column, perhaps as a composite index of hour + timestamp, so that the query above will perform really quickly.
ALTER TABLE demo1
ADD COLUMN hour1 tinyint GENERATED ALWAYS AS (HOUR(timestamp)) STORED,
ADD KEY (hour1, timestamp);
The result query would be:
SELECT
d.timestamp, d.*
FROM demo1 d
WHERE 1
AND d.timestamp > CURDATE() - INTERVAL 30 DAY
AND hour1 = 16;
More info on that here:
https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html
https://dev.mysql.com/doc/refman/5.7/en/generated-column-index-optimizations.html
I need to create a report on a monthly or daily basis (whichever is more easy) for a specific table containing the number of records that got updated, inserted or deleted in this period.
The table contains a column named updatedate and another named deleted where the value 0 means it is not deleted, and the value 1 means it was deleted. Finally, there is the primary key column, named id.
The following code returns the records deleted for a certain period of time:
SELECT * FROM orders
WHERE updateDate >='2019-01-01 00:00:00'
AND updateDate <'2019-02-13 00:00:00' AND deleted = '1'
Which queries should one run also, in order to get a report of the newly created - inserted records?
I guess one should also somehow count the number of ids that exist in the starting date, and then the number of ids that exist in the end date, and then do the subtraction in order to get the number of the newly inserted records? Ideally i would like to have these reports in separate files
CREATE TABLE orders
(
id INT PRIMARY KEY AUTO_INCREMENT,
updatedate DATETIME,
product_id INT,
deleted INT,
customer_id INT
);
INSERT INTO orders (updatedate, product_id, deleted, customer_id)
VALUES
('2019-08-15 12:20:20', '1', '0', '123'),
('2019-08-15 12:20:20', '2', '0', '123'),
('2019-08-17 16:43:09', '4', '0', '456'),
('2019-08-18 09:21:43', '8', '0', '789'),
('2019-08-18 14:23:11', '12', '0', '123'),
('2019-08-21 08:34:21', '19', '0', '456');
example output of the updated records: (assuming the record ids are not new for the month under question)
date total_updates
2009-08-15 2
2009-08-17 1
2009-08-18 2
2009-08-21 1
Same table is needed for the records deleted and created in a month basis. This must be based only on the record ids that differ from the previous month.
ie if id 88 was not in the table orders in the last day of the previous month, then this is a newly inserted record. If id 13 was in the table orders in the last previous month's last day, and in this month's last day it is not, then this is a deleted record (something which may also occur from the column deleted combined with the updatedate column)
So this report could look like:
January:
123 records inserted
456 records deleted
EDIT: as was kindly spotted, in the comments, this approach is not totally safe, since we may loose some actions. Could you please elaborate on the solution
"A safer approach is to capture all events to a log using triggers and analyse that" given the fact that any change to the current scheme is not allowed, but we can store data in a new external scheme.
I have a table with column timestam which stores a timestamp with this format: "2012-12-10 21:24:30"
I am looking for a SQL Query that takes the current timestamp and subtracts it with the one in the column and gives the difference in this format:
"3 Hours and 2 mins Remaining"
Looking for a MySQL Query that does that.
use TIMESTAMPDIFF
TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)
where unit argument, which should be one of the following values:
MICROSECOND (microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH,
QUARTER, or YEAR.
my approach : set unit as SECOND and then use SEC_TO_TIME
SELECT SEC_TO_TIME(TIMESTAMPDIFF(SECOND,`table`.`time_column`,CURRENT_TIMESTAMP()))
// will return in hh:mm:ii format
update
Return yes if HourDifference are less than 48 hours? otherwise no
SELECT IF(TIMESTAMPDIFF(HOUR,`time_column`,CURRENT_TIMESTAMP())< 48 ,'yes','no')
Assume your table name is 'testtable'
Table create query is given below
CREATE TABLE `testtable` (
`id` INT(2) NOT NULL AUTO_INCREMENT,
`period` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
Insert some data to test my query. Query to insert some data is given below
INSERT INTO `testtable` (`id`, `period`) VALUES
(1, '2012-12-10 17:21:09'),
(2, '2012-11-06 18:21:12'),
(3, '2012-12-06 18:21:18'),
(4, '2012-12-06 19:21:24'),
(5, '2012-12-06 18:21:27');
Now execute following query to get your answer
SELECT *,
CONCAT(HOUR(difftime), ' hours ', MINUTE(difftime), ' Minutes ',
SECOND(difftime), ' seconds remaining') AS timetaken
FROM (SELECT *,
SEC_TO_TIME(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(
ttable.period)) AS
diffTime
FROM testtable ttable) AS temptable1
Output is given below
The column 'timetaken' will display answer.
I am stuck with this issue for a while now any solutions are welcomed.
I have a table in MySQL and i am storing a timestamp.
Now lets say if i search on the basis of only date it works.
SELECT *
FROM table
WHERE timestamp > "2012-03-12";
this fetches all data where timestamp value is greater than 2012-03-12 00:00:00.
what i want is a query like this :
SELECT *
FROM table
WHERE timestamp > "10:20:09";
where all records with tie greater than 10:20:09 is fetched irrespective of the date.
Use this statement (it will get the time from your datetime column and compare it with the time)
SELECT *
FROM table
WHERE DATE_FORMAT(yourDatecolumn, '%H:%i:s') > '10:20:00'
Warning
This time format is for EU times (where 1pm = 13), if you want US format, use '%h:%i:s'