I have two tables in a MySQL 5.7.28 database. One table with submitted XML data from a form dumped into a single column called xmlData
The second is a table with serves as a datasource for a Datatables based JS site, called Employees
When the xml data is first submitted to the xmlData table, I use the MySQL trigger below to parse and insert the data into Employees.
use test;
DELIMITER $$
DROP TRIGGER IF EXISTS test.Update_xmlData$$
CREATE TRIGGER test.Update_xmlData AFTER INSERT ON xmlData
FOR EACH ROW BEGIN
replace INTO employees (first_name, last_name, startTime, endtime, date)
select ExtractValue(xmlData, '/Data/Employee/first_name') as first_name,
ExtractValue(xmlData, '/Data/Employee/last_name') as last_name,
ExtractValue(xmlData, '/Data/Employee/StartTime') as startTime,
ExtractValue(xmlData, '/Data/Employee/EndTime') as endtime,
ExtractValue(xmlData, '/Data/Employee/date') as date
from xmlData;
END
The output of which looks like this
---------------------------------------------------------------------
first_name | last_name | startTime | endTime | Date
---------------------------------------------------------------------
Luke | Skywalker | 08:00 | 15:00 | 2019-12-05
----------------------------------------------------------------------
Santa | Clause | 08:00 | 14:00 | 2019-12-25
----------------------------------------------------------------------
This trigger works fine and inserts the data properly. The complication is that there maybe multiple start and endtimes in the submitted xmlData row. One set for each day of the week.
For the time being, I'd like to query the submitted XML and persist these values in the Employees table as separate rows. For example, if there are Monday, Tuesday and Wednesday start/end times
the inserted data would look like this:
---------------------------------------------------------------------
first_name | last_name | startTime | endTime | Date
---------------------------------------------------------------------
Luke | Skywalker | 08:00 | 15:00 | 2019-12-05
----------------------------------------------------------------------
Luke | Skywalker | 09:00 | 17:45 | 2019-12-06
----------------------------------------------------------------------
Luke | Skywalker | 06:00 | 18:00 | 2019-12-07
----------------------------------------------------------------------
Santa | Clause | 08:00 | 15:00 | 2019-12-25
----------------------------------------------------------------------
What would be the best approach for updating the trigger to insert new rows IF there are existing StartTime/EndTime for additional days of the week? Is 1 trigger even still viable at this point?
In plain English, I was thinking something along the lines of :
IF TuesdayStartTime and TuesdayEndTime EXISTS THEN insert into Employees another row retaining the same name field values, increment date by 1 day,
IF WednesdayStartTime and WednesdayEndTime EXISTS THEN insert into EMployees another row retaining the same name field values and increment date by 2 days
Submitted XML that is being queried and inserted into employees table:
XML Sample Source Schwartz 08:00 09:00 11:0018:0020191221051312
As Barmar described I can create a loop.
I also found a less elegant way that works by extracting the submitted date and using multiple triggers for each day of the week:
DATE_ADD(ExtractValue(xmlData, '/Data/Employee/date'), interval 1 Day) as date for trigger_Monday
DATE_ADD(ExtractValue(xmlData, '/Data/Employee/date'), interval 2 Day) as date for trigger_Tuesday
Creating an Index of type Unique on the Employees table prevents duplicates.
Related
I am working on a booking system where users can book certain services online. I am stuck on finding and displaying available time slots within a specific day. I know the length of the needed time slot is 1 hour and the business hours.
Is there a way to show time slots that has not yet been booked on a certain day and display only the available time slots that is available to be booked in a dropdown select form?
If a customer selects a specific day and clicks "Select Day" then it needs to query the DB and return the results.
My SQL structure is as follows
|id | title | start_time | end_time | booking_date |
| 1 | Name1 | 2022-05-12 08:00:00 | 2022-05-12 09:00:00 | 2022-05-12 |
| 2 | Name2 | 2022-05-12 10:00:00 | 2022-05-12 11:00:00 | 2022-05-12 |
| 3 | Name3 | 2022-05-12 13:00:00 | 2022-05-12 14:00:00 | 2022-05-12 |
| 4 | Name4 | 2022-05-12 14:00:00 | 2022-05-12 15:00:00 | 2022-05-12 |
as per above the select form should display the timeslots that is not already taken.
09:00 - 10:00
12:00 - 13:00
15:00 - 16:00
It would be something like:
select
id, title
from
<table>
where
start_time between '2022-05-12 00:00:00' and '2022-05-12 11:59:59'
and
booking_date is null
I don't know the name of your table, so you would need to replace <table> with that. I'm also assuming that "booking_date" will have a value to indicate that time slot has been reserved, that it's a date field, and it will be null if that slot hasn't been selected. However, booking_date could have a different purpose.
This is a lazy answer
(because I think just use SQL will do it, use subSelect and other function, but I don't know how to do, sorry.)
get today occupy time:
SELECT id, TIME(start_time) AS s_time FROM tablename
WHERE start_time >= '2022-05-12 00:00:00'
AND start_time < '2022-05-13 00:00:00'
diff time in php:
$sqlResult = []; // sql result
$timeAll = [
'00:00:00',
'01:00:00',
'02:00:00',
'03:00:00',
... // TODO: we need fill it
'23:00:00',
];
foreach ($sqlResult as $item) {
if (isset($timeAll[$item['s_time']])) {
unset($timeAll[$item['s_time']]);
}
}
return $timeAll;
// TODO: javascript or other client code can use it.
ref knowledge link:
MySQL SELECT WHERE datetime matches day (and not necessarily time)
If you choose 2022-05-26, and Peter is occupying room F25 from 2022-05-16 until 2022-05-29, it means the date you select must be out of this range.
So, the query below will only return rooms that were not booked on that day.
SELECT b.id, b.room_id as available_room FROM booking as b
WHERE(
unix_timestamp('$mydate')
NOT BETWEEN unix_timestamp(b.start_date)
AND unix_timestamp(b.end_time)
)
AND unix_timestamp(b.end_time) < unix_timestamp('$mydate');
Assuming $mydate is the variable that contains the date selected by the user, the above query will return rooms that will be available in the future on that particular day.
I need to create a date range in a table that houses transaction information. The table updates sporadically throughout the week from a manual process. Each time the table is updated transactions are added up to the previous Sunday. For instance, the upload took place yesterday and so transactions were loaded through last Sunday (Feb 26th). If it had been loaded on Wednesday it would still be dated for Sunday. The point is that I have a moving target with my transactions and also when the data is loaded to the table. I am trying to fix my look back period to the date of the latest transaction then go three weeks back. Here is the query that I came up with:
SELECT distinct TransactionDate
FROM TransactionTABLE TB
inner join (
SELECT distinct top 21 TransactionDate FROM TrasactionTABLE ORDER BY TransactionDate desc
) A on TB.TransactionDate = A.TransactionDate
ORDER BY TB.TransactionDate desc
Technically this code works. The problem that I am running into now is when there were no transactions on a given date, such as bank holidays (in this case Martin Luther King Day), then the query looks back one day too far.
I have tried a few different options including MAX(TransactionDate) but if I use that in a sub-query or CTE then use the new value in a WHERE statement as a reference I only get the max value or the value I subtract that statement by. For instance if I say WHERE TransactionDate >= MAX(TransactionDate)-21 and the max date is Feb 26th then the result is Feb 2nd instead of the range of dates from Feb 2nd through Feb 26th.
IN SUMMARY, what I need is a date range looking three weeks back from the date of the latest transaction date. This is for a daily report so I cannot hardcode the date in. Since I am also using Excel Connections the use of Declare statements is prohibited.
Thank you StackOverflow gurus in advance!
You could use something like this:
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
select top (21)
[Date]=convert(date,dateadd(day, row_number() over (order by (select 1))-1
, dateadd(day,-20,(select max(TransactionDate) from t) ) ) )
from n as deka
cross join n as hecto
order by [Date]
)
select Date=convert(varchar(10),dates.date,120) from dates
rextester demo: http://rextester.com/ZFYV25543
returns:
+------------+
| Date |
+------------+
| 2017-02-06 |
| 2017-02-07 |
| 2017-02-08 |
| 2017-02-09 |
| 2017-02-10 |
| 2017-02-11 |
| 2017-02-12 |
| 2017-02-13 |
| 2017-02-14 |
| 2017-02-15 |
| 2017-02-16 |
| 2017-02-17 |
| 2017-02-18 |
| 2017-02-19 |
| 2017-02-20 |
| 2017-02-21 |
| 2017-02-22 |
| 2017-02-23 |
| 2017-02-24 |
| 2017-02-25 |
| 2017-02-26 |
+------------+
I just found this for looking up dates that fall within a given week. The code can be manipulated to change the week start date.
select convert(datetime,dateadd(dd,-datepart(dw,convert(datetime,convert(varchar(10),DateAdd(dd,-1/*this # changes the week start day*/,getdate()),101)))+1/*this # is used to change the week start date*/,
convert(datetime,convert(varchar(10),getdate(),21))))/*also can enter # here to change the week start date*/
I've included a screenshot of the results if you were to include this with a full query. This way you can see how it looks with a range of dates. I did a little manipulation so that the week starts on Monday and references Monday's date.
Since I am only looking back three weeks a simple GETDATE()-21 is sufficient because as the query moves forward through the week it will look back 21 days and pick the Monday at the beginning of the week as my start date.
I am looking to create a booking system. On one end you have a client looking to book an appointment and on the other end you have a provider who has a schedule that a client can book against
When signing up as a provider they are allowed to pick their days of work and hours. They have html check-boxes which represent which days they can select and once they select a day the hours are are displayed (drop-downs in angular) as you can see below
html schedule form
On the MySQL side I am thinking I can have a table which has a column for each day and have a comma separated list in there for the start time, end time, lunch time and lunch length
i.e. Provider selects Monday and Tuesday to work from the hours below
Provider 'Schedule' Table
|ScheduleID|ProviderID|Monday |Tuesday |Wednesday|Thursday|Friday|Saturday|Sunday|
|----------|----------|--------|--------|---------|--------|------|--------|------|
|1 | 2 |09:00am,|10:00am,| | | | | |
| | |08:30pm,|07:00pm,| | | | | |
| | |12:00pm,|01:00pm,| | | | | |
| | |30 min |60 min | | | | | |
|----------|----------|--------|--------|---------|--------|------|--------|------|
The table would have a schedule id and a provider id which links back to the "provider" table to link the provider to his schedule
Or is this better?
|-------------|-------------|----------|-----------|----------|------------|--------------|
| schedule_id | provider_id | week_day |start_time | end_time | lunch_time | lunch_length |
|-------------|-------------|----------|-----------|----------|------------|--------------|
| 1 | 1 | Monday | 06:00 AM | 08:00 PM | 12:30 PM | 60 |
|-------------|-------------|----------|-----------|----------|------------|--------------|
| 2 | 1 | Friday | 06:00 AM | 08:00 PM | 12:30 PM | 60 |
|-------------|-------------|----------|-----------|----------|------------|--------------|
| 3 | 2 | Tuesday | 06:00 AM | 08:00 PM | 12:30 PM | 60 |
|-------------|-------------|----------|-----------|----------|------------|--------------|
if not post something that is
Before I go into how I believe you should structure your Provider 'Schedule' Table, please make sure to, in the future, remove fluff.
More on fluff here.
It may serve you better to make the following changes:
make all column headers lowercase, as this might prevent errors if you attempt to query your database another way
change scheduleId to id
Instead of having seven columns, one for every day of the week, you could simply put a weekDay column that stores the value of that weekday
Then create columns for startTime, endTime, lunchTime and lunchLength
Finally, create a scheduleId column that ties together all the different weekday rows of someone's schedule to one provider
Some considerations:
Instead of having strings "Monday" or "Sunday" in the weekDay column you could instead insert 0..6, where 0 is a Sunday and 6 is a Saturday to make it more compatible with other languages
You could always just keep scheduleId in this table and create another table with the individual schedule days and link them with a foreign key, but this might prove to cause more problems than it's worth
Keeping that lunchLength as just an integer, as that will make everything easier
The reasoning behind splitting up the data as much as possible is because if you are querying using another language you might need to go through all the extra work of splitting those Monday and Tuesday columns if you just want the startTime for instance.
Hopefully the above is either a solution or allows you to consider another approach.
Here is a Java Android Library that you can convert into JavaScript: https://bitbucket.org/warwick/schedule_utils_demo/src/master/
Running the code in a client side language will save your server the burden as scheduling code is very inefficient.
Hope this helps.
This is what I have:
days_of_week
+----+-------------------+
| id | name |
+----+-------------------+
| 1 | Monday |
| 2 | Tuesday |
| 3 | Wednesday |
| 4 | Thursday |
| 5 | Friday |
| 6 | Satday |
| 7 | Sunday |
+----+-------------------+
time
+----------+-------------+
| id | time |
+----------+-------------+
| Integer | hh:mm:ss |
+----+-------------------+
schedule
+---------+---------+----------+---------+
| id | user_id | time_id | day_id |
+---------+---------+----------+---------+
| Integer | Integer | Integer | Integer |
+---------+---------+----------+---------+
Where should I put the activity column, i.e. Breakfast 08:30 for example. Now 'Breakfast' has to be stored somewhere here. I cannot figure out where for the moment, but if anyone knows how to correctly Normalize this please share with me, and tell my why you are doing it that way or recommend that. Thanks a lot in advance.
What I want to achieve:
Monday: Date of that day here
08:00 Breakfast
08:30 Something else
09:00 Introduction
Tuesday: Date of that day here
08:00 Breakfast
09:00 Hackathon begins
12:30 Lunch
You get it.
To clarify:
The user can select to add a schedule, this schedule is then created and includes schedule for what will happen during those selected days, for instance, if there is an Hackathon occurring for 3 days, the user can create a schedule for those three days, with time and activity that will take place. E.g. 08:00 Breakfast, 09:00 Introduction, 09:30 Equipment Installation
Found this:
Very normalized, Method for storing/displaying repeating weekly schedule
However, it's more for repeating weekly schedule, which is not what I want to achieve.
Are you going for a repeatable week on week schedule?
If not I'd consider dropping the days of week and time tables and using a standard DATETIME field. You could pop any restrictive measures in your model validation and it could also makes detecting clashes a bit easier.
Are you looking to regularly repeat activities?
If so I'd make an activities table and reference that from the schedule.
If not, I'd probably settle for a description and time.
SIMPLE
Schedule (id, description, datetime)
REPEATABLE ACTIVITIES
Schedule (id, activity_id, datetime)
Activity (id, description)
WEEK ON WEEK SCHEDULE (w/ repeatable activities)
Schedule (id, activity_id, day_of_week_id, time)
Activity (id, description)
Day_of_week (id, title)
Always go for the simplest option that fulfills your requirements!
Normalize! Since you are already doing it:
// others omitted
activity(id, description)
day(id, time_id, activity_id)
schedule(id, day_id)
I might miss something, but open for correction.
I have a table which look like this:
Date | Day | Ingredients
-------------------------------------------
2014-08-20 | Wednesday | Salt
2014-08-21 | Thursday | Sugar
2014-08-22 | Friday | Salt&Sugar
2014-08-28 | Thursday | Salt
And I want to have only the dates there are in one week. Should I make an extra column 'Week' with the number of the week or is there a solution where I can set the beginning and the end of a week to only have the actual week. So I have all rows from the actual week.
SELECT * FROM table WHERE *`Date is in the actual week`*
You mean to get the data of current week?
Use the YEARWEEK function.
SELECT * FROM your_table
WHERE YEARWEEK(`date`, 1) = YEARWEEK(CURRENT_DATE, 1)
Update:
Use mode 1 if the beginning of week is Monday.