datetime select with -15 minute interval showing wrong result - mysql

For a room reservation page I'm making a query for entries among 3 tables. Datetime values are in one table, another table keeps the info if the room key has been checked out. And another table keeps the reservation information. If current time has past start of reservation time at least 15 minutes and the key has not been checked out, the entry should get deleted. Problem is, it deletes also future reservations, where the start time of the reservation has not past yet. My query looks like this.
SELECT dt.field_reservation_datetime_value
, dt.entity_id
, co.field_reservation_checked_out_value
, co.entity_id
, res.reservation_id
FROM field_data_field_reservation_datetime dt
JOIN field_data_field_reservation_checked_out co
ON co.entity_id = dt.entity_id
JOIN studyroom_reservation res
ON res.reservation_id = co.entity_id
WHERE co.field_reservation_checked_out_value = 0
AND DATE (dt.field_reservation_datetime_value) <= NOW() - INTERVAL 15 MINUTE
Right now it is 9:52am, this shouldn't be showing up for the next 2 hours and 38 minutes. What I get is this:
Any idea what I may doing wrong?
edit: table alias added and screenshot

Solved it with following code
SELECT dt.*, co.*, res.*
FROM field_data_field_reservation_datetime AS dt
JOIN field_data_field_reservation_checked_out AS co
ON co.entity_id = dt.entity_id
JOIN studyroom_reservation as res
ON res.reservation_id = co.entity_id
WHERE co.field_reservation_checked_out_value = 0
AND ((dt.field_reservation_datetime_value)
<= DATE_FORMAT(NOW() - INTERVAL 15 MINUTE,'%Y-%m-%d %H:%i:%s'))

Related

Subtract time from sql time column

I am trying to write a query that detect when a reservation is in the last 15 mins of it (so it knows it's nearly done). So as of now I have:
UPDATE bookings b JOIN reservation_time_data r ON r.id = b.reservation_time SET b.reservation_processed = 'ending' WHERE reservation_date LIKE ? AND CURRENT_TIME BETWEEN(r.end_time AND r.end_time - '00:15:00.000000')
Usually for adding time I would use ADDTIME() but for this I'm not sure.
You could phrase this as:
where
reservation_date like ?
and r.end_time between current_time - interval 15 minute and current_time

Retention Rate with MySQL

I try to calculate the retention rate with mysql and start with this one:
SELECT
s_order.ordertime,
DATE_SUB(future_orders.ordertime, INTERVAL 90 DAY),
count(distinct s_order.userID) as active_users,
count(distinct future_orders.userID) as retained_users
FROM s_order
LEFT JOIN s_order as future_orders on
s_order.userID = future_orders.userID
AND s_order.ordertime = DATE_SUB(future_orders.ordertime, INTERVAL 90 DAY);
This does not work - I get all users are active and therefore I added DATE_SUB(future_orders.ordertime, INTERVAL 90 DAY), to the selection criteria to see what is going on. However it returns NULL - but why?
As a reference I did take a look at this explanation:
https://www.periscopedata.com/blog/how-to-calculate-cohort-retention-in-sql.html
My table has a structure like
s_orders:
ID | userID | ordertime
I would expect a result how many different users have ordered something in general and how many have ordered something again in the last 90 days, to get the retention of the customers.
Does anybody know what am I doing wrong in MySQL?
DATE_SUB() returns null when the date value is null, so that probably why. Because you are LEFT JOIN-ing, the future_orders record can be null/non-existing

MySQL Query Multiple Joins duplicating data for each row? JIRA Database

I'm trying to pull the sum time worked for each user in a certain group over the next 30 days. I am not great at MySQL, so a lot of this may be wrong. This is from a JIRA database.
SELECT DISTINCT cu.display_name AS 'Associate', sum(wl.timeworked/3600) AS '30 Days'
FROM worklog AS wl, cwd_user AS cu
INNER JOIN cwd_membership AS cm
ON cu.directory_id=cm.directory_id
AND cu.lower_user_name=cm.lower_child_name
AND cm.membership_type='GROUP_USER'
INNER JOIN worklog
ON worklog.AUTHOR = cu.user_name
WHERE cm.lower_parent_name='atl_servicedesk_it_agents' AND wl.STARTDATE BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 30 DAY)
ORDER BY cu.last_name;
Right now it just displays the first users name with a sum total of everything in the time worked for everyone. That is obviously not what I want... If I remove the sum from timeworked it shows about half of the users from that group, but each user has a value of 16 hours for timeworked, which is incorrect. Only one user has any value for the next 30 days and it is for 16 hours, so for some reason it is duplicating this information.
Any ideas?
Got it working by taking out the INNER JOINs.
SELECT cwd_user.display_name AS 'Associate', sum(worklog.timeworked/3600) AS '30 Days'
FROM worklog, cwd_user,cwd_membership
WHERE worklog.AUTHOR = cwd_user.user_name
and cwd_user.directory_id = cwd_membership.directory_id
and cwd_user.lower_user_name = cwd_membership.lower_child_name
and cwd_membership.membership_type = 'GROUP_USER'
and cwd_membership.lower_parent_name = 'atl_servicedesk_it_agents'
and worklog.STARTDATE BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 60 DAY)
GROUP BY cwd_user. display_name
ORDER BY cwd_user.last_name;

MYSQL First and last datetime within a day

I have a table with 3 days of data (about 4000 rows). The 3 sets of data are all from a 30 minutes session. I want to have the start and ending time of each session.
I currently use this SQL, but it's quite slow (even with only 4000 records). The datetime table is indexed, but I think the index is not properly used because of the conversion from datetime to date.
The tablelayout is fixed, so I cannot change any part of that. The query takes about 20 seconds to run.. (and every day longer and longer). Anyone have some good tips to make it faster?
select distinct
date(a.datetime) datetime,
(select max(b.datetime) from bike b where date(b.datetime) = date(a.datetime)),
(select min(c.datetime) from bike c where date(c.datetime) = date(a.datetime))
from bike a
Maybe I'm missing something, but...
Isn't the result returned by the OP query equivalent to the result from this query:
SELECT DATE(a.datetime) AS datetime
, MAX(a.datetime) AS max_datetime
, MIN(a.datetime) AS min_datetime
FROM bike a
GROUP BY DATE(a.datetime)
Alex, warning, this in typed "freehand" so may have some syntax problems. But kind of shows what I was trying to convey.
select distinct
date(a.datetime) datetime,
(select max(b.datetime) from bike b where b.datetime between date(a.datetime) and (date(a.datetime) + interval 1 day - interval 1 second)),
(select min(c.datetime) from bike c where c.datetime between date(a.datetime) and (date(a.datetime) + interval 1 day - interval 1 second))
from bike a
Instead of comparing date(b.datetime), it allows comparing the actual b.datetime against a range calculated form the a.datetime. Hopefully this helps you out and does not make things murkier.

MySQL: Find Missing Dates Between a Date Range

I need some help with a mysql query. I've got db table that has data from Jan 1, 2011 thru April 30, 2011. There should be a record for each date. I need to find out whether any date is missing from the table.
So for example, let's say that Feb 2, 2011 has no data. How do I find that date?
I've got the dates stored in a column called reportdatetime. The dates are stored in the format: 2011-05-10 0:00:00, which is May 5, 2011 12:00:00 am.
Any suggestions?
This is a second answer, I'll post it separately.
SELECT DATE(r1.reportdate) + INTERVAL 1 DAY AS missing_date
FROM Reports r1
LEFT OUTER JOIN Reports r2 ON DATE(r1.reportdate) = DATE(r2.reportdate) - INTERVAL 1 DAY
WHERE r1.reportdate BETWEEN '2011-01-01' AND '2011-04-30' AND r2.reportdate IS NULL;
This is a self-join that reports a date such that no row exists with the date following.
This will find the first day in a gap, but if there are runs of multiple days missing it won't report all the dates in the gap.
CREATE TABLE Days (day DATE PRIMARY KEY);
Fill Days with all the days you're looking for.
mysql> INSERT INTO Days VALUES ('2011-01-01');
mysql> SET #offset := 1;
mysql> INSERT INTO Days SELECT day + INTERVAL #offset DAY FROM Days; SET #offset := #offset * 2;
Then up-arrow and repeat the INSERT as many times as needed. It doubles the number of rows each time, so you can get four month's worth of rows in seven INSERTs.
Do an exclusion join to find the dates for which there is no match in your reports table:
SELECT d.day FROM Days d
LEFT OUTER JOIN Reports r ON d.day = DATE(r.reportdatetime)
WHERE d.day BETWEEN '2011-01-01' AND '2011-04-30'
AND r.reportdatetime IS NULL;`
It could be done with a more complicated single query, but I'll show a pseudo code with temp table just for illustration:
Get all dates for which we have records:
CREATE TEMP TABLE AllUsedDates
SELECT DISTINCT reportdatetime
INTO AllUsedDates;
now add May 1st so we track 04-30
INSERT INTO AllUsedData ('2011-05-01')
If there's no "next day", we found a gap:
SELECT A.NEXT_DAY
FROM
(SELECT reportdatetime AS TODAY, DATEADD(reportdatetime, 1) AS NEXT_DAY FROM AllUsed Dates) AS A
WHERE
(A.NEXT_DATE NOT IN (SELECT reportdatetime FROM AllUsedDates)
AND
A.TODAY <> '2011-05-01') --exclude the last day
If you mean reportdatetime has the entry of "Feb 2, 2011" but other fields associated to that date are not present like below table snap
reportdate col1 col2
5/10/2011 abc xyz
2/2/2011
1/1/2011 bnv oda
then this query works fine
select reportdate from dtdiff where reportdate not in (select df1.reportdate from dtdiff df1, dtdiff df2 where df1.col1 = df2.col1)
Try this
SELECT DATE(t1.datefield) + INTERVAL 1 DAY AS missing_date FROM table t1 LEFT OUTER JOIN table t2 ON DATE(t1.datefield) = DATE(t2.datefield) - INTERVAL 1 DAY WHERE DATE(t1.datefield) BETWEEN '2020-01-01' AND '2020-01-31' AND DATE(t2.datefield) IS NULL;
If you want to get missing dates in a datetime field use this.
SELECT CAST(t1.datetime_field as DATE) + INTERVAL 1 DAY AS missing_date FROM table t1 LEFT OUTER JOIN table t2 ON CAST(t1.datetime_field as DATE) = CAST(t2.datetime_field as DATE) - INTERVAL 1 DAY WHERE CAST(t1.datetime_field as DATE) BETWEEN '2020-01-01' AND '2020-07-31' AND CAST(t2.datetime_field as DATE) IS NULL;
The solutions above seem to work, but they seem EXTREMELY slow (taking possibly hours, I waited for 30 min only) at least in my database.
This clause takes less than a second in same database (of course you need to repeat it manually dozen times and possibly change function names to find the actual dates). pvm = my datetime, WEATHER = my table.
mysql> select year(pvm) as _year,count(distinct(date(pvm))) as _days from WEATHER where year(pvm)>=2000 and month(pvm)=1 group by _year order by _year asc;
--ako