SQL Dealing with midnight - mysql

I'm dealing with (for me) huge SQL problem. I have table called "timeshifts" which as 4 columns:
id, name, from and to. Last two type is TIME.
Now: I have three timeshifts:
06:00 - 14:00
14:00 - 22:00
22:00 - 06:00
Now, I have to find correct shift for current time (which works like a charm), but I can't find a proper records that belong to current shift. IE. table called user_times contains fields with separate date and time values. According to current timeshift I have to find records that belongs to the timeshift. There is no problem for first two shifts, but third one passes midnight and that is my problem.
Here is the query that finds proper shift, event through midnight:
SELECT
FLOOR(SUM(time_sum) / 60) AS th,
MOD(SUM(time_sum), 60) AS tm,
t.*
FROM
ur_user_times ut,
ur_timeshifts t
WHERE CURTIME() >= IF (
t.timeshift_to < t.timeshift_from,
0,
ADDTIME(t.timeshift_from, "00:15")
)
AND CURTIME() <= ADDTIME(
IF (
t.timeshift_to < t.timeshift_from,
ADDTIME(t.timeshift_from, "10:00:00"),
t.timeshift_to
),
"00:15"
)
AND ut.`date` BETWEEN CURDATE() - INTERVAL 1 DAY AND CURDATE()
AND ut.`start` BETWEEN ADDTIME(t.`timeshift_from`, "-10:00:00") AND ADDTIME(t.`timeshift_to`, "-10:00:00")
AND ut.user_id = 40
ut.start is time value that interests us.

Try this:
select *
from timeshifts ts,
usertimes ut
where
(ts.from < ts.to and ut.start >= ts.from and ut.start <= ts.to) OR
(ts.from > ts.to and (ut.start >= ts.from or ut.start <= ts.to))

A similar query was posted a few days ago:
Please see this question:
Shift wise datetime checking in sql server query

Related

SQL - Using query with date parameters with IN used for a sub-query

I have the following query which is returning nothing:
SELECT e.`value`, e.`machine_id`, e.`date_recorded`
from engine_hours e
where e.`date_recorded` >= NOW() - INTERVAL 32 DAY
AND e.`date_recorded` <= NOW() - INTERVAL 2 DAY
AND e.`machine_id` IN (SELECT m.id FROM `machines` m WHERE m.`title` = 'ABC-123')
When I break the query and sub-query into two independent queries they work fine
Question:
How can I use what the sub-query returns to the main query, alongside the date boundaries in the WHERE section of the main query.
Clarification & Better Explanation:
I get no errors.
When I run the sub-query as a query of its own ie:
SELECT m.id FROM `machines` m WHERE m.`title` = 'ABC-123'
it returns 1234 which is correct. And when I use this returned value 1234 in the main query ie:
SELECT e.`value`, e.`machine_id`, e.`date_recorded`
from engine_hours e
where e.`date_recorded` >= NOW() - INTERVAL 32 DAY
AND e.`date_recorded` <= NOW() - INTERVAL 2 DAY
AND e.`machine_id = '1234'
I get the data I am after.
I can't seem to understand what I am doing wrong.
Explaining the dates:
I want to get the data starting from 32 days ago till 2 days ago:
where e.`date_recorded` >= NOW() - INTERVAL 32 DAY
AND e.`date_recorded` <= NOW() - INTERVAL 2 DAY
ie now is 2019-03-06, 32 days ago (NOW() - INTERVAL 32 DAY) will be 2019-02-02
and similarly 2 days ago will be 2019-03-04.
The information I want should be greater than or equal to (>=) 2019-02-02 and less then or equal to (<=) 2019-03-04.
Use join
SELECT e.`value`, e.`machine_id`, e.`date_recorded`,m.id
from engine_hours e join `machines` m on e.`machine_id`=m.id
where e.`date_recorded` >= NOW() - INTERVAL 32 DAY
AND e.`date_recorded` <= NOW() - INTERVAL 2 DAY
and m.`title` = 'ABC-123'
EDITED
I've just tried it myself, it's working fine. Each query individually is correct (syntax & logic). Both queries together is also correct (syntax & logic).
So it's either:
The machine_id in the targeted rows in engine_hours is different than 1234.
The date_recorded in the targeted rows in engine_hours is not of the date range desired.
The query you posted in StackOverflow is slightly different than the one you have in your source code.
Maybe you're including the database name in the query. If so, make sure you're targeting the correct database name.
I suggest you delete the entire query in your source code and re-write it again. You probably have some hidden character(s), wrong operator used, or alike.

Getting data of everyday's same time period

Suppose I have a table containing a month's transaction data with transaction_time stored in a DATETIME field.
I want to get all the transactions that occurred between 12:00:00 and 13:00:00, irrespective of the day. WHERE transaction_time BETWEEN x AND y would have to be date-specific, but I need that same time period of all dates.
How can I filter for such a range in a MySQL query?
You can filter on the result of applying MySQL's HOUR() function to your DATETIME value:
WHERE HOUR(transaction_time) = 12
If you need to filter across more exact time ranges, you could convert the times to seconds as follows:
WHERE TIME_TO_SEC(TIME(transaction_time)) BETWEEN TIME_TO_SEC('12:00:00')
AND TIME_TO_SEC('13:00:00')
You can use:
select * from transactions
where convert(time, transaction_time) between '12:00:00' and '13:00:00'
for MSSQL and:
select * from transactions
where extract(hour_second from transaction_time) between 120000 and 130000
for MySql.
You have two time constraints. The first is to restrict the dates to a particular month. Assume we get the first day of the month as a date parameter:
where transaction_time >= :searchMonth
and transaction_time < Date_Add( :searchMonth, interval 1 month )
Now we're only looking at rows from that month. Now limit it to the hour specified. Assume we get the hour as an integer parameter:
and extract( hour from transaction_time ) between :hr and (:hr + 1)
Now that final part is based on your own code. Let me say that when the requirements read "during a particular hour of the day" and the request reads "during the noon hour" then I am wont to write it like this:
and extract( hour from transaction_time ) >= :hr
and extract( hour from transaction_time ) < (:hr + 1)
because hour 13 (1PM) is the first click of the next hour. So if there is a transaction time at exactly 13:00:00 and you use between, then it will show up when looking at the noon hour and also when looking at the 1PM hour. That is NOT generally a desired result. You may want to verify that with your analyst.
So the complete filter, the way I would write it, is this:
where transaction_time >= :searchMonth
and transaction_time < Date_Add( :searchMonth, interval 1 month )
and extract( hour from transaction_time ) >= :hr
and extract( hour from transaction_time ) < (:hr + 1)

SQL select current week/last week

I'm looking for a way of selecting rows based on:
Current week (S-S)
Previous week (S-S)
The problem I'm having is selecting specifically from Sunday-Sunday.
At the moment I'm using:
SELECT SUM(time)
FROM `time`
WHERE `projectid` = '$pid' && created > DATE_SUB(NOW(), INTERVAL 1 WEEK)
Any help would be great, thanks!
MySQL does have a WEEK function that you can use:
SELECT SUM(time)
FROM `time`
WHERE
`projectid` = '$pid'
AND created > NOW() - INTERVAL 2 WEEK
AND WEEK(created) IN (WEEK(NOW()), WEEK(NOW() - INTERVAL 1 WEEK))
Notes
The first condition (created > NOW() - INTERVAL 2 WEEK) is needed to get all the data of the current and previous weeks first and then restrict for the two weeks you are interested in. Otherwise, if you had enough data, you would get the aggregation of all data of the corresponding weeks of every year in your table. It also has the added benefit of allowing the query to use an index on that field.
You also need to use "WEEK(NOW() - INTERVAL 1 WEEK)" due to the first week of the year. Otherwise, WEEK(NOW()) - 1 would have sufficed

Mysql time range query using extract

I'm trying to get an mysql query similar to date_trunc in psql.
Unfortunate Mysql do not have date_trunc function and I found I can use extract instead in Mysql.
What I want to do is write a script which i will run let say 10 minutes past each hour but I want to only select data from begin of an hour till end of this hour.
For example I will run script 12:10 and I want to display data from 11:00:00 till 11:59:59.
In PSQL query would look like that:
SELECT *
FROM data
WHERE time > ( date_trunc('hour',now()) - interval '1 hour' )
AND time <= ( date_trunc('hour',now()) ) ORDER BY time;
I was trying to use extract in similar fashion but I have no rows returned or error :/
Query below returns for example some narrowed data but it's like 2 hours each day from day one when database was started not last hour only:
SELECT *
FROM data
WHERE extract(hour from cr_date) between extract(hour from now()) - interval 1 hour)
AND extract(hour from now())
ORDER BY cr_date;
Any ideas how this can be achieved? or what I'm doing wrong in this query?
Hour is only an integer, so it's finding any matches between , for example, 9 and 10, regardless of the date.
I would recommend
select * FROM data
where cr_date >= date(now()) + INTERVAL hour(now())-1 HOUR
and cr_date <= date(now()) + INTERVAL hour(now()) HOUR
date(now()) returns midnight, and hour(now()) returns the number of hours since midnight
so, at 11:10 am, it should result in a results between midnight + 10 hours (10 am) and midnight + 11 hours (11 am)

Retrieve data whose Date between start and end date is between today and after ten day in rails or sql

I want to retrieve data whose Date between start and end date is between today and after ten day.I'm doing it in rails but even if i get the query in MySQL i can convert it to rails active record.
Something like this one :
select * from users where( between users.from and users.to = between '2012-11-25 11:52:33' and '2012-12-05 11:52:33')
The interval (a, b) overlaps with (c, d) iff a < d and b > c. Also, the curdate() function returns the current date ("today"). To calculate the date ten days into the future you can use + interval 10 day.
Combining these bits of information you get:
select ... where users.to > curdate()
and users.from < curdate() + interval 10 day
Follwing is the logic snippet not the exact code though. Please try.
select * from users
where users.fromDate between '2012-11-25 11:52:33' and '2012-12-05 11:52:33'
and users.toDate between '2012-11-25 11:52:33' and '2012-12-05 11:52:33';
Check the following sample code in * SQLFIDDLE as well
EDITING AS PER YOUR QUESTION'S REPHRASING..
Guess you are better off with,
where users.from between users.from and users.from + interval 10day
and users.to <= user.from + interval 10 day
That means, your from date can be anything (today, yesterday, one month back, two years to future...). Hence your to-date will be validated against any date that is 10 days interval from the above from-date
Hope it makes sense... but again, Joni's answers fills for your today's consition. :)