How to fetch data from specific hours in SQL - mysql

I have a problem with CosmosDB, which also allows some SQL queries.
I have a database that is being uploaded every hour with a new record.
I would like to fetch everything from the last day from 8PM to 8AM current day and another query from 8AM to 8PM the current day. I have a timestamp in the db in ISO format. How the potential query (or queries) would look like?
I achieved to fetch last 24h like this, but I really want to stick to the time range 8PM-8AM and then 8AM-8PM, basically two shifts. Previous one and the current one.
function getLast24hTime(){
var date = new Date();
var a = date.setHours(-24);
return a;
}
and then:
SELECT * FROM c where c.time >= udf.getLastHourTime()
tl;dr Everyday I want to fetch specific hours range from the previous day (8pm-8am) + specific hours from the current day (8am-8pm). How.

in mysql you could do
the other shift is analog
CREATE TABLE be (
`date` DATETIME
);
INSERT INTO be
(`date`)
VALUES
('2022-01-13 20:41:24'),
('2022-01-13 21:41:24'),
('2022-01-14 01:41:24'),
('2022-02-14 09:41:24'),
('2022-02-14 10:41:24');
SELECT `date` from be WHERE `date` > CURDATE() - INTERVAL 1 DAY + INTERVAL 20 HOUR
ANd `date` < CURDATE() + INTERVAL 8 HOUR
| date |
| :------------------ |
| 2022-01-13 20:41:24 |
| 2022-01-13 21:41:24 |
| 2022-01-14 01:41:24 |
db<>fiddle here

Related

MySQL MAX foreach day

I have the following table with measured values:
datetime | water | air | conductivity | ...
2021-07-17 16:44:39 | 13,9 | 18,6 | 357 | ...
I am currently querying the values ​​for a period of time:
SELECT * FROM kn1 WHERE datetime > TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 month)) ORDER BY datetime
Now I don't want to get every value, just the highest value of each day.
In general, I can query the highest value through
SELECT MAX(water) FROM kn1 WHERE datetime > TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 month)) ORDER BY datetime
But this way I get the highest value for the entire period. But I would like to get the highest value for each day in the period.
How can I do this?
Thanks in advance
Use GROUP BY:
SELECT DATE(datetime), MAX(water)
FROM kn1
WHERE datetime > CURDATE() - INTERVAL 1 month)
GROUP BY DATE(datetime);
Note that I modified the WHERE clause to simplify it. Presumably, you don't date about the current time, just the date, so this uses the current date. Second, there is no need for TIMESTAMP, and third, I find interval arithmetic to be simpler without additional functions.

Dynamic due dates checking with the given period of dates

id start_date interval period
1 1/22/2018 2 month
2 2/25/2018 3 week
3 11/24/2017 3 day
4 7/22/2017 1 year
5 2/25/2018 2 week
the above is my table data sample. start_dates will be expired based on interval and period(i.e id-1 will have due date after 2 months from the start_date, id-2 will have due after 3 weeks vice versa). period is enum of (day,week,month,year). Client can give any period of dates. let's say 25-06-2026 to 13-07-2026 like that.. I have to return the ids whose due dates falls under that period.I hope i made my question clear.
Here what i have done to resolve this. I am using mysql 5.7. I found ways to achieve this with recursive CTE's.(not available in mysql 5.7). and there is a way to achieve this by populating virtual records by using inline sub queries along with unions and its a performance killer and there is restriction of population of records.(like given in the link Generating a series of dates) I have reached a point to get results for a single date which is very easy. Below is my query(in oracle)
select id
from (select a.*,
case
when period='week'
then mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),7*interval)
when period='month' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd')=to_char(start_date,'dd')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date),interval)=0
then 0
when period='year' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd-mm')=to_char(start_date,'dd-mm')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date)/12,interval)=0
then 0
when period='day'
and mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),interval)=0
then 0 else 1 end filter from kml_subs a)
where filter=0;
But I need to do this for a period of dates not a single date. Any suggestions or solutions will be much appreciated.
Thanks,
Kannan
Assuming this is an Oracle question and not MySQL:
I think the first thing that you need to do is calculate when the due date is. I think a simple case statement can handle that for you:
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
end due_date
Then, using that new due_date field, you can check if the due date falls between the desired date range.
select *
from(
select id,
start_date,
interval,
period,
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
else null end due_date
from data)
where due_date between date '2018-02-25' and date '2018-03-12'
The above query checking between 2/25/18 and 3/12/18 produces the following output using your data:
+----+-------------+----------+--------+-------------+
| id | start_date | interval | period | due_date |
+----+-------------+----------+--------+-------------+
| 2 | 05-FEB-2018 | 3 | week | 26-FEB-2018 |
| 5 | 25-FEB-2018 | 2 | week | 11-MAR-2018 |
+----+-------------+----------+--------+-------------+

Why doenst my Update query have an effect on my table content?

I have a table that depicts future flight arrival times. After each flight arrival time has past (or expired) I would like the query to update the arrival time by inserting the next arrival time, which is usually a week from the current day/time.
Although my query doesn't yield any error messages, it doesn't have an effect on expired arrival times as it should.
Find below the query:
// The update should happen between 31 minutes to and hour after the flight has arrived.
UPDATE flightSched
SET `arrivalTime`= ADDDATE(NOW(), INTERVAL 1 WEEK)
WHERE arrivalTime BETWEEN SUBTIME(NOW(), '00:31:00')
AND SUBTIME(NOW(),'01:00:00')
ORDER BY arrivalTime ASC
Find below a simlpe version of my table:
+-------------+---------------------+
| FlightNo | arrivalTime |
+-------------+---------------------+
| ET821 | 2013-11-24 08:05:24 |
| MS838 | 2013-11-24 10:05:24 |
| H7361 | 2013-11-24 13:15:06 |
+-------------+---------------------+
If the current time is 09:45, then flight number ET821 arrival time should be updated to 2013-12-01 08:05:24, Please help me understand why this update doesn't happen?
Your update doesn't produce any results because your date range in WHERE clause is incorrect. The upper value in BETWEEN operator is less than the lower value.
According to your requirements instead of
BETWEEN SUBTIME(NOW(), '00:31:00') AND SUBTIME(NOW(),'01:00:00')
^^^^^^^
it should be at least
BETWEEN SUBTIME(NOW(), '00:31:00') AND ADDTIME(NOW(),'01:00:00')
^^^^^^^
Try it the other way
UPDATE flightSched
SET arrivalTime = arrivalTime + INTERVAL 1 WEEK
WHERE arrivalTime >= NOW() - INTERVAL 31 MINUTE
AND arrivalTime <= NOW() + INTERVAL 1 HOUR
Note: make sure that you have an index on arrivalTime column.
Here is SQLFiddle demo

Generate Monthly XML from a table containing date range

I have a table as -
test_table(booking_id, booking_description, start_date, end_date)
Sample Data -
1 | Some booking | 06/30/2013 | 08/01/2013
2 | Some new one | 08/05/2013 | 09/01/2013
3 | Some new two | 09/03/2013 | 09/05/2013
Now I want to generate a monthly xml file from using some java code (No problem in it, I would write), I would be passing the month and year (basically start and end date of the month) to mysql query and I want some table as -
month = 7, year 2013
1 | Some booking | 07/01/2013
1 | Some booking | 07/02/2013
...
Month = 9, year = 2013
2 | Some new one | 09/01/2013
| | 09/02/2013
3 | Some new two | 09/03/2013
...
I was looking to use a java loop from start date to end date and query mysql to find out whether this date comes in the date range or not, if it comes I would add the details else I would add blanks. But that is going to be horrible approach (will go for 30 times mysql look ups) and I am considering it as last option.
Is there any other way around with one or two mysql query and get the data in the format.
EDIT:
month = 7, year = 2013
Select *
from booking_details
where month(start_date) <= 7 and year(start_date) <= 2013 and
month(end_date) >= 7 and year(end_date) >= 2013
I developed this query but still not sure would it over all the possible scenarios.
Based on my understanding of the question you want something like this:
declare #date datetime
Select booking_id, booking_description, start_date --you don't indicate which date field you want in the results
from test_table
where (start_date between #date and date_add(#date, INTERVAL 1 MONTH))
or (end_date between #date and date_add(#date, INTERVAL 1 MONTH))
SQL is probably not exact, I know TSQL not MySQL but this should be close.

select several averages of an interval

So my coworker is looking at a schema which could be described as something like this:
+--------------------+-----------+
| DATETIME timestamp | INT value |
+--------------------+-----------+
Every 5 minutes a row is entered with the value for that moment.
Here's where it gets tricky. He wants to get the average of every 8 hour period within a 7 day interval.
Certainly, I can think of solutions which involve some client side code, we were wondering if it was possible to do more in SQL.
So in essence, he wants:
SELECT timestamp, value
FROM table
WHERE timestamp >= NOW() - INTERVAL 7 DAYS
AND timestamp <= NOW();
And then breaking that up into 8 hour blocks, and averaging the contents of each block. (each block should have 12 rows, and there should be 3 blocks per day).
try
SELECT avg(`value`)
FROM `table`
WHERE timestamp >= NOW() - INTERVAL 7 DAY AND timestamp <= NOW()
group by concat(date(`timestamp`), case when hour(`timestamp`) between 0 and 7 then 1
when hour(`timestamp`) between 8 and 15 then 2
else 3 end)
If you are not tied by only doing it in your request, you could try the following method of splitting the intervals before doing the request :
boundary1 = NOW()
boundary2 = NOW()
FOR i = 0 to 21 //7 days, 3 intervals of 8 hours per days
boundary1 = boundary2
boundary2 = boundary1 - seconds(8 hours)
req = "SELECT timestamp, value FROM table WHERE timestamp >= "+boundary2+" AND timestamp <= "+boundary1
ENDFOR