I want to draw a graph accurately, Time vs Site Visits.
X axis will be 4, 8, 12, 16, 20, 24. That's increments of four hours.
Y axis total number of visits by first 4 hours, then by next four hours etc.
How can I do it using MySql? There might be some tricks using GROUP BY, but I couldn't get it. I stored all visit to my site, used unix time stamp for time.
The query can be like this -
SELECT FLOOR(HOUR(FROM_UNIXTIME(unix_ts)) / 4) period, COUNT(*) visit_count_per_4_hours FROM visits_table
WHERE DATE(FROM_UNIXTIME(unix_ts)) = DATE(NOW())
GROUP BY period;
This query returns visits for specified day, otherwise calculation should be modified.
TRY
SELECT SUM( visit ) , HOUR( `time_column` )
FROM time_table
WHERE DATE_SUB( `time_column` , INTERVAL 4 HOUR )
GROUP BY HOUR( `time_column` )
working example
CREATE TABLE IF NOT EXISTS `time_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`waqt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`visit` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
--
-- Dumping data for table `time_table`
--
INSERT INTO `time_table` (`id`, `waqt`, `visit`) VALUES
(1, '2011-07-28 13:29:04', 3),
(2, '2011-07-28 15:29:10', 4),
(3, '2011-07-28 13:45:35', 7),
(4, '2011-07-28 15:00:47', 5),
(5, '2011-07-28 14:45:03', 6),
(6, '2011-07-28 13:00:21', 3);
and then i execute per hour visit
SELECT SUM(visit), HOUR(waqt)
FROM time_table
WHERE DATE_SUB(`waqt`,INTERVAL 1 HOUR) GROUP BY HOUR(waqt)
Related
I have a database with the following columns. I have added some sample data to show formatting.
date, time, amount
2021-10-14, 13:00, 15.40
2021-10-14, 13:01, 9.34
2021-10-14, 13:02, 10.12
2021-10-14, 13:03, 7.44
There are 2.6 million rows in the database spanning two years.
Each row is an increment of 1 minute.
I need to write sql that will output and group rows that are continuous by minute for the same date, where the amount is greater than 8.00 and there are a minimum of 3 consecutive rows.
This would then find an example like:
2021-11-30, 14:44, 8.04
2021-11-30, 14:45, 9.41
2021-11-30, 14:46, 9.27
2021-11-30, 14:47, 10.54
2021-11-30, 14:48, 11.09
2022-03-13, 08:22, 36.44
2022-03-13, 08:23, 17.38
2022-03-13, 08:24, 11.86
So if I understand correctly you only want to select the rows that are part of a 3 minute (minimum) consecutive sequence where amount >= 8 ?
I'm not sure about the performance but this seems to work:
Setup:
CREATE TABLE series
(
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
date DATE NOT NULL,
time TIME NOT NULL,
datetime DATETIME GENERATED ALWAYS AS (TIMESTAMP(date, time)),
amount decimal(5, 2),
INDEX (amount)
);
INSERT INTO series (date, time, amount)
VALUES ('2021-11-30', '14:40', 7),
('2021-11-30', '14:41', 8),
('2021-11-30', '14:42', 8),
('2021-11-30', '14:43', 8),
('2021-11-30', '14:44', 8),
('2021-11-30', '14:45', 7),
('2021-11-30', '14:46', 8),
('2021-11-30', '14:47', 8),
('2021-11-30', '14:48', 8),
('2021-11-30', '14:49', 7),
('2021-11-30', '14:50', 8),
('2021-11-30', '14:51', 8),
('2021-11-30', '14:52', 7)
;
The solution:
SELECT date, time, T.amount
FROM (SELECT date,
time,
datetime,
amount,
LAG(datetime, 2) OVER (order by datetime) AS tmin2,
LAG(datetime, 1) OVER (order by datetime) AS tmin1,
LEAD(datetime, 1) OVER (order by datetime) AS tplus1,
LEAD(datetime, 2) OVER (order by datetime) AS tplus2
FROM series
WHERE amount >= 8) T
WHERE TIME_TO_SEC(TIMEDIFF(T.datetime, T.tmin2)) = 120
OR TIME_TO_SEC(TIMEDIFF(T.datetime, T.tplus2)) = -120
OR (TIME_TO_SEC(TIMEDIFF(T.datetime, T.tmin1)) = 60 AND TIME_TO_SEC(TIMEDIFF(T.datetime, T.tplus1)) = -60)
ORDER BY datetime;
Explanation:
First we filter out the values < 8 using a WHERE-statement.
Then we peek into the previous two and next two rows ordered by datetime to see if the current to is part of a 3 min sequence and filter based on that criteria.
Here is my solution:
Table Definition :
CREATE TABLE YourTbl (
date date DEFAULT NULL,
time time DEFAULT NULL,
amount decimal(4,2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO YourTbl VALUES
('2021-10-12','16:30', 20.40),
('2021-10-12','14:21', 19.34),
('2021-10-14','13:00', 15.40),
('2021-10-14','13:01', 9.34),
('2021-10-14','13:02', 10.12),
('2021-10-14','13:03', 7.44),
('2021-11-30', '14:44', 8.04),
('2021-11-30', '14:45', 9.41),
('2021-11-30', '14:46', 9.27),
('2021-11-30', '14:47', 10.54),
('2021-11-30', '14:48', 11.09),
('2022-03-13', '08:22', 36.44),
('2022-03-13', '08:23', 17.38),
('2022-03-13', '08:24', 11.86);
Lets test the query:
SELECT
date,time,amount FROM
(SELECT date,time,amount,
LEAD(minute(time),1) OVER(PARTITION BY date ORDER BY time) as leadtime,
LAG(minute(time),1) OVER(PARTITION BY date ORDER BY time) as lagtime,
(minute(time) - LAG(minute(time),1) OVER(PARTITION BY date ORDER BY time)) as minute_forward_difference,
(LEAD(minute(time),1) OVER(PARTITION BY date ORDER BY time) - minute(time)) as minute_backward_difference
FROM YourTbl
WHERE amount > 8.0
) as tblder
WHERE (minute_forward_difference = 1) OR (minute_backward_difference = 1)
GROUP BY date,time,amount;
Resultset:
Here is the schema:
CREATE TABLE `available_timings` (
`id` bigint(20) NOT NULL ,
`from_time` time DEFAULT NULL,
`to_time` time DEFAULT NULL
);
INSERT INTO `available_timings` (`id`, `from_time`, `to_time`) VALUES
(1, '15:11:00' , '17:15:00'),
(2, '15:11:00', '15:11:00'),
(3, '09:00:00', '12:30:00'),
(4, '15:40:00', '15:40:00'),
(5,'13:30:00', '17:15:00'),
(6, '16:10:00', '16:10:00'),
(7, '07:45:00', '11:45:00'),
(8, '19:00:00', '22:30:00'),
(9, '16:14:00', '16:14:00'),
(10, '09:30:00', '17:45:00'),
(11, '10:30:00','15:15:00');
http://sqlfiddle.com/#!9/fc9afe/2
I am trying to achieve whether the current time falls between from time and to time in mysql
SELECT *
FROM `available_timings`
WHERE curtime() >=`from_time` or curtime() <=`to_time`
i have searched many forum and also tried few queries but couldn't succeeded.
Can any one help me here to solve my problem
Thank you
Use BETWEEN
SELECT *
FROM `available_timings`
WHERE curtime() BETWEEN `from_time` AND `to_time`
Use AND instead of OR
WHERE curtime() >= `from_time`
AND curtime() <= `to_time`
You don't want any of these conditions to be true. You want both of them to be true.
I have a table which has a date column, some self-reports of happiness in another column, and a flag column which indicates a gym day.
I want to get the average happiness scores on the day before, the day of, and the day after a gym session.
If you imagine this table, the averages should return day_before = 1, day_of = 2, and day_after = 3.
So the set up is like in this fiddle, although in my actual database the gym flag column is joined in from a separate table.
CREATE TABLE test
(`date` datetime, `gym` int, `happiness` int)
;
INSERT INTO test
(`date`, `gym`, `happiness`)
VALUES
('2019-01-06 00:00:00', NULL, 1),
('2019-02-06 00:00:00', 1, 2),
('2019-03-06 00:00:00', NULL, 3),
('2019-04-06 01:00:00', NULL, 1),
('2019-05-06 01:00:00', 1, 2),
('2019-06-06 01:00:00', NULL, 3),
('2019-07-06 01:00:00', NULL, 1),
('2019-08-06 01:00:00', 1, 2),
('2019-09-06 01:00:00', NULL, 3)
;
I tried using a subquery to return when the "gym" column in date - 1 = 1, and also use the results in a case which would have "day of", "day before", and "day after" strings. Then I could simply group by that column. I couldn't get this to work and I'm not even sure if that's something you can do.
Use two self-joins.
SELECT AVG(before.happiness) AS day_before, AVG(current.happiness) AS day_of, AVG(after.happiness) AS day_after
FROM test AS current
JOIN test AS before ON before.date = DATE_SUB(current.date, INTERVAL 1 DAY)
JOIN test AS after ON after.date = DATE_ADD(current.date, INTERVAL 1 DAY)
WHERE current.gym = 1
I have a database table with an auto-update column which is required to be in the TIMESTAMP format, this saves dates in the form YYYY-MM-DD HH:mm:ss for each time a row is updated.
On reading statements that date comparisons are (possibly very) processor heavy, the preferred method seems to be to use MySQL BETWEEN statement to check and return updates that have occurred in the last 24 hours.
A reference: https://stackoverflow.com/a/14104364/3536236
My SQL
I have removed some details that take up space that are outside the scope of this question, such as some columns
-- Generation Time: Oct 14, 2015 at 04:54 PM
-- Server version: 5.5.45-cll
-- PHP Version: 5.4.31
--
-- Table structure for table `check_log`
--
CREATE TABLE IF NOT EXISTS `check_log` (
`table_id` int(8) NOT NULL AUTO_INCREMENT,
`last_action` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`ip_addr` varchar(60) NOT NULL,
`submit_fail` varchar(1) NOT NULL,
PRIMARY KEY (`fail_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=14 ;
--
-- Dumping data for table `check_log`
--
INSERT INTO `check_log` (`table_id`, `last_action`, `ip_addr`, `submit_fail`) VALUES
(2, '2015-10-14 14:08:30', '92.99.252.185', 'N'),
(3, '2015-10-14 14:09:23', '92.99.252.185', 'N'),
(4, '2015-10-14 14:09:25', '92.99.252.185', 'N'),
(5, '2015-10-14 14:09:38', '92.99.252.185', 'N'),
(6, '2015-10-14 14:14:22', '92.99.252.185', 'N'),
(7, '2015-10-14 14:17:13', '92.99.252.185', 'N'),
(8, '2015-10-14 14:20:51', '92.99.252.185', 'N'),
(9, '2015-10-14 14:20:52', '92.99.252.185', 'N'),
(10, '2015-10-14 14:50:34', '92.99.252.185', 'N'),
(11, '2015-10-14 15:29:07', '92.99.252.185', 'N'),
(12, '2015-10-14 15:31:04', '92.99.252.185', 'N'),
(13, '2015-10-14 15:32:00', '92.99.252.185', 'N');
My Query
Now, my query wants to return all the rows that fit the criteria that have been updated in the last 24hours. So:
SELECT * FROM `check_log` WHERE `ip_addr` = '92.99.252.185' AND
(`last_action` BETWEEN date_sub(CURDATE() , INTERVAL -1 DAY ) AND CURDATE())
AND `submit_fail` = 'N'
I wrote the query in this shape because I wanted to explore how BETWEEN ... AND ... handled other ANDS in the same query, and hence for my own clarity I encased the BETWEEN statement in brackets ().
I have tried a range of minorly different syntaxes for this query including:
SELECT * FROM `check_login` WHERE `ip_addr` = '92.99.252.185' AND
(DATE_FORMAT(`last_action`, '%Y-%m-%d') BETWEEN date_sub(CURDATE() , INTERVAL -1 DAY ) AND CURDATE())
and pure date check:
SELECT * FROM `check_login` WHERE
`last_action` BETWEEN date_sub(CURDATE() , INTERVAL -1 DAY ) AND CURDATE()
Each time the MySQL returns Zero Rows (not an error) but zero rows found.
I have viewed and compared at least a dozen similar answers on SO about the comparison of dates and am at a bit of a loss how I'm not getting the rows returned that I'm expecting with my query.
(I am ideally wanting to use the BETWEEN form as this table will, when in use be reaching several thousands of rows. )
What can I do to make the comparison work?
How does the BETWEEN clause handle other ANDs, is it suitable to encase in brackets (for clarity)
Is there a more efficient / suitable method to compare timestamp column dates?
It appears that DATE_SUB() is subtraction so I did not need to do -1 on the INTERVAL <value> DAY section of the SQL, however, the INTERVAL does accept negative values but that would overall be a subtraction of a negative and so a +1 Day interval.
I had originally thought for some reason DATE_SUB had stood for substitution as the allowance of negative values in the value part - to me - meant that there was no need for a data addition function as well.
I wasted half a day reading up and trying to work out how this logic worked.
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.