MySQL - Modify datetime columns based on additional datetime columns - mysql

I had a rough time figuring out how to title this, but here's an explanation...
I have two tables
Table #1:
--------------------------------------------------------------
| id | start | end | duration |
-------------------------------------------------------------
| 1 | 2013-10-01 09:00:00 | 2013-10-01 09:30:00 | 30 |
-------------------------------------------------------------
| 2 | 2013-10-02 10:00:00 | 2013-10-02 10:30:00 | 30 |
--------------------------------------------------------------
| int | datetime | datetime | int |
--------------------------------------------------------------
Table #2:
---------------------------------------------------
| id | start | end |
---------------------------------------------------
| 3 | 2013-10-01 09:00:00 | 2013-10-01 17:00:00 |
---------------------------------------------------
| 4 | 2013-10-02 09:00:00 | 2013-10-02 17:00:00 |
---------------------------------------------------
| int | datetime | datetime |
---------------------------------------------------
What I'm trying to do is grab the all records from table #2 match any table #1 rows that fall on the same date and within the same datetime and modify the result set by removing the times from table #1...
An example result would be...
---------------------------------------------------------
| table2id | start | end |
---------------------------------------------------------
| 3 | 2013-10-01 09:30:00 | 2013-10-01 17:00:00 |
---------------------------------------------------------
| 4 | 2013-10-02 09:00:00 | 2013-10-02 10:00:00 |
---------------------------------------------------------
| 4 | 2013-10-02 10:30:00 | 2013-10-02 17:00:00 |
---------------------------------------------------------
How can this be achieved?

Though I can't be sure this logic would be correct, something like this might be close to what you're looking for:
UPDATE tbl2
SET start = (SELECT end FROM tbl1 WHERE start = tbl2.start)
It's not terribly clear how these two tables relate. However, id clearly doesn't. The only two values that match in your example are the start values.

SELECT Table2.id, Table1.end_date , Table2.end_date
FROM table1 AS Table1, table2 AS Table2
WHERE
Table1.start_date >= Table2.start_date
AND Table1.end_date <= Table2.end_date
UNION
SELECT Table2.id, Table2.start_date , Table1.start_date
FROM table1 AS Table1, table2 AS Table2
WHERE
Table1.start_date >= Table2.start_date
AND Table1.end_date <= Table2.end_date
this works but will give you an extra record with identical start and end that you have to manually delete
---------------------------------------------------------
| table2id | start | end |
---------------------------------------------------------
| 3 | 2013-10-01 09:30:00 | 2013-10-01 17:00:00 |
| 4 | 2013-10-02 10:30:00 | 2013-10-02 17:00:00 |
| 3 | 2013-10-01 09:00:00 | 2013-10-01 09:00:00 | --> Extra Record
| 4 | 2013-10-02 09:00:00 | 2013-10-02 10:00:00 |

Related

Filtering out duplicate data based on more than one value in MySQL 8

I have a simple table like so
+----+---------------------+
| id | datetime |
+----+---------------------+
| 1 | 2019-05-05 16:00:00 |
| 1 | 2019-05-05 17:00:00 |
| 1 | 2019-05-05 18:00:00 |
| 1 | 2019-05-05 18:00:00 |
| 2 | 2019-05-05 16:00:00 |
| 2 | 2019-05-05 17:00:00 |
| 2 | 2019-05-05 18:00:00 |
| 3 | 2019-05-05 17:00:00 |
| 3 | 2019-05-05 17:00:00 |
+----+---------------------+
I'd like to filter out all the rows with duplicate datetime entries for each id, so that I may end up with a table like this:
+----+---------------------+
| id | datetime |
+----+---------------------+
| 1 | 2019-05-05 16:00:00 |
| 1 | 2019-05-05 17:00:00 |
| 1 | 2019-05-05 18:00:00 |
| 2 | 2019-05-05 16:00:00 |
| 2 | 2019-05-05 17:00:00 |
| 2 | 2019-05-05 18:00:00 |
| 3 | 2019-05-05 17:00:00 |
+----+---------------------+
What is the easiest way to do this in MySQL?
EDIT: Let's say I had another column called weight that assigns a numerical weight to each row of data. Is there a way to tell MySQL to filter out the duplicate datetime entries for each id based on which one has the largest weight?
use distinct
select distinct id,datetime from table_name
after your edit it seems you need row_number()
select * from
(select *,
row_number() over(partition by id,datetime order by weight desc) rn
from table_name
) a where a.rn=1
You seem to want:
select t.*
from t
where t.weight = (select max(t2.weight)
from t t2
where t2.id = t.id and t2.datetime = t.datetime
);

Compare output of select statement

My Table1
| Participantsid | Validfrom | Validto |
| 2,4,1 | 2016-02-21 10:22:00 | 2016-02-21 12:22:00 |
| 2,4,1 | 2016-03-04 10:00:00 | 2016-03-04 10:25:00 |
| 2,3,4,1 | 2016-02-19 10:43:00 | 2016-02-19 11:08:00 |
| 2,3,4,1 | 2016-02-22 11:32:00 | 2016-02-22 11:57:00 |
| 4,6,5 | 2016-02-20 17:00:00 | 2016-02-20 18:00:00 |
| 1,2,5 | 2016-02-22 18:00:00 | 2016-02-22 19:00:00 |
| 2,3,6,1 | 2016-03-23 10:00:00 | 2016-03-23 11:00:00 |
| 1,2,3,5 | 2016-02-20 12:00:00 | 2016-02-20 14:00:00 |
| 2,6 | 2016-02-20 12:00:00 | 2016-02-20 13:00:00 |
Another Table2
+--------------+------------+
| EmployeeName | EmployeeID |
+--------------+------------+
| Mathews | 1 |
| Gerald | 2 |
| Bravo | 3 |
| Smith | 4 |
| George | 5 |
| Bailey | 6 |
| Stephen | 9 |
| Balu c | 10 |
I have some inputid's=1,5,6.
Now I have to compare this input id's with Participantsid from table1 for a given validfrom and validto date and if there is a match I need to get the name corresponding to that id.
Emaple:- inputid's=1,2,3 for from- 2016-02-22 18:00:00, to-2016-02-22 19:00:00
it should give me o/p =mathews,gerald
I am currently writing two select statements and using one for loop which gives me the result but its wrong
I am trying to do it in a single query but no way near to my required output.please help
Desired result can be achieved by using group_concat and find_in_set with sub-query.
SQLFiddle:
http://sqlfiddle.com/#!9/ce893/1
select group_concat(EmployeeName) as `o/p`
from Table2
where FIND_IN_SET(EmployeeID,
(select Participantsid from Table1
where Validfrom = '2016-02-22 18:00:00' and Validto = '2016-02-22 19:00:00'));

MySQL: MIN and Group By: Get the first timestamp of 12x # events for each person's day

What I want to do is to get the smallest scheduled time for each user in a given day. For the examples below I've highlighted just that day's events, which I will filter on my end simply by adding
AND DATE_ADD(scheduled, INTERVAL -$timezone_offset MINUTE)>='$given_day 00:00:00'
AND DATE_ADD(scheduled, INTERVAL -$timezone_offset MINUTE)< '$next_day 00:00:00'
For a simplified example I've got two tables:
checkpoints
+------+---------+----------+---------------------+
| id | type_id | event_id | scheduled |
+------+---------+----------+---------------------+
| 1111 | 9 | 2222 | 2015-06-05 12:00:00 |
| 1150 | 1 | 2222 | 2015-06-05 10:00:00 |
| 1200 | 11 | 3333 | 2015-06-05 23:00:00 |
| 1305 | 1 | 4444 | 2015-06-05 15:00:00 |
| 1400 | 2 | 4444 | 2015-06-05 05:00:00 |
| 1405 | 3 | 4444 | 2015-06-05 19:00:00 |
| 1500 | 1 | 5555 | 2015-06-05 17:00:00 |
| 1505 | 9 | 5555 | 2015-06-05 18:00:00 |
+------+---------+----------+---------------------+
events
+------+---------+---------------------+
| id | user_id | start |
+------+---------+---------------------+
| 2222 | 3 | 2015-06-05 11:00:00 |
| 3333 | 5 | 2015-06-05 23:00:00 |
| 4444 | 2 | 2015-06-05 07:00:00 |
| 5555 | 5 | 2015-06-05 19:00:00 |
+------+---------+---------------------+
I want to query such that I get the following:
+------+---------+---------------------+---------------------+
| id | user_id | start | scheduled |
+------+---------+---------------------+---------------------+
| 1150 | 3 | 2015-06-05 11:00:00 | 2015-06-05 10:00:00 |
| 1500 | 5 | 2015-06-05 19:00:00 | 2015-06-05 17:00:00 |
| 1400 | 2 | 2015-06-05 07:00:00 | 2015-06-05 05:00:00 |
+------+---------+---------------------+---------------------+
That is: the first scheduled time of any given driver's day.
The query I thought would work is:
SELECT
checkpoints.id AS id,
user_id,
start,
MIN(scheduled) AS scheduled
FROM checkpoints
LEFT JOIN events ON event_id=events.id
WHERE DATE_ADD(scheduled, INTERVAL -240 MINUTE)>='2015-06-05 00:00:00'
AND DATE_ADD(scheduled, INTERVAL -240 MINUTE)<'2015-06-06 00:00:00'
AND user_id IS NOT NULL
GROUP BY user_id, DATE(DATE_ADD(scheduled, INTERVAL -240 MINUTE));
The problem is that I'm getting the wrong checkpoint id and start time, even though the user_id and earliest are correct. To illustrate the problem, I see a result like:
+------+---------+---------------------+---------------------+
| id | user_id | start | scheduled |
+------+---------+---------------------+---------------------+
| 1200 | 5 | 2015-06-05 23:00:00 | 2015-06-05 17:00:00 |
+------+---------+---------------------+---------------------+
What am I doing wrong?
Your query would be illegal for most of SQL implementations. MySQL allows to SELECT columns that are neither aggregated nor included in GROUP BY clause.
However, the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate

MySQL last value of day

I am trying to construct a query that produces one value per day and I want that value to be the last recorded value of the day. This is what my table looks like (actual dataset contains a row for each minute):
+------------+----------+-------+
| Date | Time | Value |
+------------+----------+-------+
| 2015-06-14 | 13:00:00 | 3 |
| 2015-06-14 | 14:00:00 | 5 |
| 2015-06-15 | 11:00:00 | 6 |
| 2015-06-15 | 17:00:00 | 9 |
| 2015-06-16 | 09:00:00 | 2 |
| 2015-06-16 | 10:00:00 | 4 |
+------------+----------+-------+
I would like the outcome of the query to look like this:
+------------+----------+-------+
| Date | Time | Value |
+------------+----------+-------+
| 2015-06-14 | 14:00:00 | 5 |
| 2015-06-15 | 17:00:00 | 9 |
| 2015-06-16 | 10:00:00 | 4 |
+------------+----------+-------+
What would the SQL-statement need to be to retrieve this result? Any help is much appreciated!
select t1.date,
t1.time,
t1.value
from table t1
where t1.time= (select max(t2.time)
from table t2
where t2.date = t1.date);

Appointment system mysql query

I need to write a query to select all free slots from appointment table but have problem writing such complex query. Maybe someone could help me I will try to explain what I need to get.
I have table structure:
+---------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| patient_id | int(11) | YES | MUL | NULL | |
| start_time | datetime | NO | | NULL | |
| end_time | datetime | NO | | NULL | |
+---------------+----------+------+-----+---------+----------------+
The problem is that I need to get free slots. For e.g. The works starts at 8:00 AM and ends at 8:00PM and this goes from Monday to Saturday. From last appointment free space should like 1 year in advance. So here is example response that I expect:
+---------------------+---------------------+------------------+
| Free Time Start | Free Time End | Free Time Length |
+---------------------+---------------------+------------------+
| 2014-09-15 08:00:00 | 2014-09-15 08:30:00 | 30 |
| 2014-09-15 09:30:00 | 2014-09-15 12:00:00 | 150 |
| 2014-09-15 15:00:00 | 2014-09-15 20:00:00 | 300 |
| 2014-09-16 09:00:00 | 2014-09-16 11:30:00 | 150 |
| 2014-09-16 13:00:00 | 2014-09-16 17:00:00 | 240 |
| 2014-09-16 18:00:00 | 2015-09-16 18:00:00 | 525600 |
+---------------------+---------------------+------------------+
The sample data for results above:
+----+------------+---------------------+---------------------+
| id | patient_id | start_time | end_time |
+----+------------+---------------------+---------------------+
| 1 | 1 | 2014-09-15 08:30:00 | 2014-09-15 09:30:00 |
| 2 | 1 | 2014-09-15 12:00:00 | 2014-09-15 15:00:00 |
| 3 | 1 | 2014-09-16 08:00:00 | 2014-09-16 09:00:00 |
| 4 | 1 | 2014-09-16 11:30:00 | 2014-09-16 13:00:00 |
| 5 | 1 | 2014-09-16 17:00:00 | 2014-09-16 18:00:00 |
+----+------------+---------------------+---------------------+
So in plain query should:
Get free space 08:00:00 <= x <= 20:00:00 and through monday to saturday (Other days, hours should be skipped)
After last appointment free time range should be 1 year in advance
Sorry if similar questions exists I could not reuse that solutions for hour/day offsets and 1 year in advance... I tried to do this in PHP but it tooks a really long time...