I have a table with created_time field.
There is a requirement to find out all entries between two dates, between a particular time interval.
For example, if I want to find all entries between April 1st 2018 to April 30th 2018 with time interwal between 2.30 PM to 4.30 PM, what would be the ideal query ?
select * from my_table where created_time between '2018-04-01
14:30:00' and '2018-04-30 16:30:00'
You need to split compare Date value and Time value.
You can try this query.
TestDLL
CREATE TABLE my_table (
created_time DATETIME
);
INSERT INTO my_table VALUES ('2018-04-01 14:00:00');
INSERT INTO my_table VALUES ('2018-04-01 14:50:00');
INSERT INTO my_table VALUES ('2018-04-04 10:00:00');
INSERT INTO my_table VALUES ('2018-04-01 15:00:00');
Query
select * from my_table
where
(created_time between '2018-04-01' and '2018-04-30')
AND
(CAST(created_time AS time) > CAST('14:30:00' AS time) AND CAST(created_time AS time) < CAST('16:30:00' AS time))
[Results]:
| created_time |
|----------------------|
| 2018-04-01T14:50:00Z |
| 2018-04-01T15:00:00Z |
SQLFiddle
Related
I'm trying to query for users with birthdays falling between a given date range.
The users table stores birthdays in a pair of int columns: dob_month (1 to 12) and dob_day (1 to 31). The date range I'm querying with is a pair of date-time strings, including the year.
Here's what I've got so far:
SELECT *
FROM `users`
WHERE DATE(CONCAT_WS('-', 2023, dob_month, dob_day)) BETWEEN '2023-03-01 00:00:00' AND '2023-03-31 23:59:59'
However, this doesn't work when the date range spans multiple years.
For example, 2023-12-15 00:00:00 and 2024-01-10 23:59:59.
How can I work around this? Thanks!
You can solve this by joining to a set of rows with individual dates.
Suppose you had another table called dates which had one row per day, spanning the whole range you need.
mysql> create table dates (date date primary key);
mysql> insert into dates(date)
with recursive cte as (
select '2023-01-01' as date
union
select cte.date + interval 1 day from cte where cte.date < '2025-01-01'
)
select * from cte;
Query OK, 732 rows affected (0.01 sec)
Now it's easy to query a subset of dates:
mysql> SELECT date
FROM dates
WHERE dates.date BETWEEN '2023-12-15 00:00:00' AND '2024-01-10 23:59:59';
...
27 rows in set (0.00 sec)
We create a sample user with a dob of January 3.
mysql> create table users ( id serial primary key, dob_month tinyint, dob_day tinyint);
mysql> insert into users set dob_month = 1, dob_day = 3;
You can join your users table to that subset of dates where the month and day match.
mysql> SELECT date FROM users JOIN dates
ON dob_month = MONTH(date) AND dob_day = DAY(date)
WHERE dates.date BETWEEN '2023-12-15 00:00:00' AND '2024-01-10 23:59:59';
+------------+
| date |
+------------+
| 2024-01-03 |
+------------+
In the below code, the logic is to convert dob_month and dob_day into a date and then do the comparison using BETWEEN operator.
Now the year value used for date conversion is based on the below logic :
Use the year value the same as that of "from date". If the date is less than the "from date", then push it to the next year. Use BETWEEN operator to check if the date is within the given date range. This logic is applied because to use BETWEEN operator the date has to be greater than or equal to the "from date" keeping month and day values intact.
Note Date_add(Date_add(Makedate(some_year_value, 1), INTERVAL (dob_month)-1 month), INTERVAL (dob_day)-1 day) is repeated 3 times. It is for creating a date out of the year, month, and day values.
SET #fromdate = date('2023-09-01 00:00:00');
SET #fromyear = year(#fromdate);
SET #todate = date('2024-02-28 23:59:59');
CREATE TABLE users
(
id SERIAL PRIMARY KEY,
dob_month TINYINT,
dob_day TINYINT
);
INSERT INTO users
SET dob_month = 2,
dob_day = 1;
SELECT *
FROM users
WHERE CASE
WHEN Date_add(Date_add(Makedate(#fromyear, 1),
INTERVAL (dob_month)-1 month),
INTERVAL (dob_day)-1 day) < #fromdate THEN
Date_add(Date_add(Makedate(#fromyear + 1, 1),
INTERVAL (dob_month)-1 month),
INTERVAL (dob_day)-1 day) BETWEEN #fromdate AND #todate
ELSE Date_add(Date_add(Makedate(#fromyear, 1),
INTERVAL (dob_month)-1 month),
INTERVAL (dob_day)-1 day) BETWEEN #fromdate AND #todate
end;
Psuedo code for understanding the crux:
SELECT *
FROM users
WHERE CASE
WHEN Date(from_date_year,dob_month,dob_day) < #fromdate THEN
Date(from_date_year,dob_month,dob_day) BETWEEN #fromdate AND #todate
ELSE Date(from_date_year + 1,dob_month,dob_day) BETWEEN #fromdate AND #todate
end;
I have a table containing alternating ON & OFF events with its timestamp. How do i calculate total time between each ON & OFF?
Status Timestamp
============================
ON 2019-01-01 07:00:00
OFF 2019-01-01 08:30:00
ON 2019-01-01 09:00:00
OFF 2019-01-01 10:00:00
ON 2019-01-01 10:30:00
OFF 2019-01-01 11:30:00
Consider the following...
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
dt DATETIME NOT NULL,
status VARCHAR(5) NOT NULL
);
INSERT INTO my_table VALUES
(1,'2015-01-01 13:00:00','ON'),
(2,'2015-01-01 13:10:00','OFF'),
(3,'2015-01-01 13:20:00','ON'),
(4,'2015-01-01 13:30:00','OFF'),
(5,'2015-01-01 13:35:00','ON'),
(6,'2015-01-01 13:40:00','OFF'),
(7,'2015-01-01 13:50:00','ON'),
(8,'2015-01-01 15:00:00','OFF');
SELECT x.*,
TIMEDIFF(MIN(y.dt),x.dt) AS TimeDiff
FROM my_table AS x
INNER JOIN my_table AS y ON y.dt >= x.dt
WHERE x.status = 'ON' AND y.status = 'OFF'
GROUP
BY x.id;
Refer DB FIDDLE For More:
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=00dc040da540f852f08b2f02750bc16d
CREATE TABLE events (
`status` VARCHAR(3),
`timestamp` VARCHAR(19)
);
INSERT INTO events
(`status`, `timestamp`)
VALUES
('ON', '2019-01-01 07:00:00'),
('OFF', '2019-01-01 08:30:00'),
('ON', '2019-01-01 09:00:00'),
('OFF', '2019-01-01 10:00:00'),
('ON', '2019-01-01 10:30:00'),
('OFF', '2019-01-01 11:30:00');
SELECT
TIME_FORMAT(SEC_TO_TIME(TIME_TO_SEC(
SUM(TIMEDIFF(offtime, ontime))
)), '%H:%i')
AS total FROM (
SELECT e.timestamp AS offtime, (SELECT timestamp
FROM events AS st WHERE st.timestamp < e.timestamp AND st.status = "ON"
ORDER BY st.timestamp DESC LIMIT 1) AS ontime
FROM events AS e WHERE e.status='OFF') AS onoffs
Selects every OFF record, joins the most recent ON record to it, sums time ranges. With your data it gives the result: total 03:30
Doesn't account for open ranges. E.g. if the data series is started with OFF; or if it ends with ON, the time up to current moment would not be counted.
https://www.db-fiddle.com/f/hr27GhACxGd7ZvFaa52xiK/0#
I want to find out if there is a difference in the result between using the two following queries on the same table:
SELECT * FROM table WHERE DATE BETWEEN 01/01/2007 AND 30/9/2007
and
SELECT * FROM table WHERE DATE >= 01/01/2007 AND DATE <= 30/9/2007
Is there a difference between using BETWEEN and >= <=?
SELECT * FROM order_details WHERE order_date BETWEEN CAST('2014-02-01' AS DATE) AND CAST('2014-02-28' AS DATE);
This MySQL BETWEEN condition example would return all records from the order_details table where the order_date is between Feb 1, 2014 and Feb 28, 2014 (inclusive). It would be equivalent to the following SELECT statement:
SELECT * FROM order_details WHERE order_date >= CAST('2014-02-01' AS DATE) AND order_date <= CAST('2014-02-28' AS DATE);
Source
So the answer is NO, there is no difference
I have records like:
2017-07-24 16:59:32
2017-07-24 17:53:38
2017-07-24 22:26:08
2017-07-24 23:04:54
2017-07-25 08:33:43
2017-07-25 10:06:47
And I want to write an sql query which compares only the time part of timestamp, as example:
SELECT * FROM table WHERE date BETWEEN '17:30:00' and '22:30:00'
Check only the time and ignore the date. Is it possible to do so?
I'm using MySQL
SELECT * FROM table WHERE hour('date') = 9;
Takes full hour, as I sometimes need to take only half of an hour.
This should work:
SELECT * FROM table
WHERE
(HOUR(date) BETWEEN 18 AND 21) OR
(HOUR(date) = 17 AND MINUTE(date)>=30) OR
(HOUR(date) = 22 AND MINUTE(date)<=30);
Or another approach would be to convert to DATE, add the hours and minutes and then use between.
SELECT * FROM table
WHERE date BETWEEN
ADDDATE(ADDDATE(DATE(date), INTERVAL 17 HOUR), INTERVAL 30 MINUTE)
AND
ADDDATE(ADDDATE(DATE(date), INTERVAL 22 HOUR), INTERVAL 30 MINUTE);
You can convert the DATETIME to a time and use that in the comparison.
Given the sample code:
CREATE TABLE Table1
(
Column1 VARCHAR(50),
Column2 VARCHAR(50),
Timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO
Table1
(Column1, Column2, Timestamp)
VALUES
('Valid', 'Time', '2017-01-01 17:43:01'),
('Invalid', 'Time', '2017-01-01 16:00:43');
You could query it like the following:
SELECT
*,
DATE_FORMAT(`timestamp`, '%H:%i:%s') AS Time
FROM
Table1
WHERE
DATE_FORMAT(`timestamp`, '%H:%i:%s') BETWEEN '17:30:00' AND '22:30:00';
SQL Fiddle
If I have a column in a table called creation_date in the database that contain unix timestamp values, how do I get results returned that were only created between for example May 10th 2013 and June 9th 2013?
I tried the below but all I got returned was 0; which isn't correct.
SELECT COUNT(*) FROM my_table WHERE FROM_UNIXTIME(creation_date) BETWEEN '05-10-2013 00:00:00' AND '06-09-2013 23:59:59';
1) If creation_date is a timestamp stored as TIMESTAMP:
SELECT
COUNT(*)
FROM
my_table
WHERE
creation_date
BETWEEN '2013-05-10 00:00:00'
AND '2013-06-09 23:59:59';
2) If creation_date is a timestamp stored as INT:
SELECT
COUNT(*)
FROM
my_table
WHERE
creation_date
BETWEEN UNIX_TIMESTAMP('2013-05-10 00:00:00')
AND UNIX_TIMESTAMP('2013-06-09 23:59:59');