MySQL, transfer values from one table to another depending of the weekday - mysql

I have one table where every worker chose the meal that he wants for each day of the week (kitchen_wishes), and contains an ID column, and columns Monday, Tuesday, etc. The selection is stored as an integer value.
and another table where the selection for THAT day is copied from the first table (food_for_today). This table contains one ID column (in same order as the first table) and another column - what_to_eat. It is pretty straight forward.
I try to create a daily event in the SQL database which would move the values for that day from the first table to the second, every day at 9:00, but I have various issues, generally with copying values from one table to another depending on the day.
Here is my code:
```
CREATE EVENT update_kitchen_wishes
ON SCHEDULE
EVERY 1 DAY
STARTS '2020-09-02 09:00:00' ON COMPLETION PRESERVE ENABLE
DO
SET #today = WEEKDAY(CURDATE()+1);
INSERT INTO food_for_today (what_to_eat)
SELECT
CASE
WHEN #today = 1 THEN Monday
WHEN #today = 2 THEN Tuesday
WHEN #today = 3 THEN Wednesday
WHEN #today = 4 THEN Thursday
WHEN #today = 5 THEN Friday
WHEN #today = 6 THEN Saturday
WHEN #today = 7 THEN Sunday
END
FROM kitchen_wishes;

Related

How to check if a date is a specific day in the week in MySQL?

I have a MySQL table presence with following structure:
id: 1
uid: 14
start: 2021-11-01 00:00:00
end: 2021-12-31 00:00:00
repetitive: 1
This row gives me the information, that the user 14 is present every Monday from 2021-11-01 to 2021-12-31.
SELECT 1
FROM presences
WHERE 2021-11-15 BETWEEN DATE(`start`) AND DATE(`end`)
checks if the given date (2021-11-15) is between his presence dates but how can I add logic to check for "every Monday"? Additionally, if end is null, it should check for every Monday in future without end.
Monday is given by start date and can be every other day as well.
repetitive gives me to check that given day by start. If repetitive is 0, it should just check like my query already does, if the date is between start and end.
Human query: get all rows from presence table where given date is between start and end (if end is not null) and where given day is day of start.
Get all rows from presence where given date is between start and end,
if end is not null and where given day is day of start.
could be humanly translated to:
SELECT *
FROM t
WHERE '2021-11-15' >= `start`
AND (
'2021-11-15' <= `end` OR
`end` IS NULL
)
AND (
repetitive = 0 OR
repetitive = 1 AND WEEKDAY('2021-11-15') = WEEKDAY(`start`)
)
Directly answering the question posed in the title of your post you can use:
DAYOFWEEK(date): Returns the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday). These index values correspond to the ODBC standard.
WEEKDAY(date): Returns the weekday index for date (0 = Monday, 1 = Tuesday, … 6 = Sunday).
DAYNAME(date): Returns the name of the weekday for date. The language used for the name is controlled by the value of the lc_time_names system variable
But in your description of the query you want, you say
Get all rows from presence where given date is between start and end, if end is not null and where given day is day of start. (my emphasis)
which implies you want the number of instances of start date day name/index in your range. To do this you can use different methods to extrapolate your range to rows and the pick the required day from it.
A calendar table would be best, as you can already build in the day name/index in to the data in the table.
SELECT COUNT(*) as monday_count
FROM presences JOIN calendar
ON calendar.day_date BETWEEN DATE(`start`) AND DATE(`end`)
WHERE `end` IS NOT NULL AND calendar.day_name = DAYNAME(`start`);
Here's an example of building a calendar table, it's MSSQL specific so some of the queries might need to be modified for MySQL, but you get the idea.

Using BETWEEN Condition Without Including Two Dates

Is there a simple way of using BETWEEN but not including the two dates you want to check between? I noticed if you use BETWEEN it includes the start and end date itself. I've been working on a booking system and want to stop guests booking dates in between another booking or overlapping another booking.
E.g. if there's a booking for 20th May until the 25th May I don't want anyone to be able to book those dates regardless of the start and end date of the new booking. I do, however, want users to be able to have their end date on the same day as a different booking's start date or the start date on the same day as a different booking's end date.
Originally I had:
SELECT id
FROM table
WHERE (? BETWEEN arrive_date AND depart_date)
OR (? BETWEEN arrive_date AND depart_date)
The first ? is for the new arrive date and the second ? is for the new end date.
But when checking it included the start and end date then I tried to work out the correct formula and got this:
SELECT id FROM table
WHERE (? BETWEEN arrive_date - INTERVAL 1 DAY AND depart_date - INTERVAL 1 DAY)
OR (? BETWEEN arrive_date + INTERVAL 1 DAY AND depart_date - INTERVAL 1 DAY)
It seemed to be fine but then I noticed if I book, for example, 9th November and 10th November I can then also book 6th 15th November.
I thought what I had was correct and I am still working it all out but if someone can see where I am going wrong that would be helpful!
If there is a row in the table with arrive_date less than the queried departure date and depart_date greater than the queried arrival date then you will get as result 'booked', else you will get 'free':
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM `table`
WHERE :depart_date > arrive_date AND :arrive_date < depart_date
) THEN 'booked'
ELSE 'free'
END result
Replace :arrive_date and :depart_date with the dates that you will pass as parameters.
See the demo.

MySQL Event Scheduler on a specific time every Saturday

Here's my query
CREATE EVENT saturday
ON SCHEDULE
EVERY 6 DAY
STARTS (TIMESTAMP(CURRENT_DATE) + INTERVAL 1 DAY)
DO UPDATE `AttrInfo`.`attrID` SET `4` = '2000';
Idea behind is that it will double the value for Saturday, and then I need to find a way for it to change the value back to 1000 when Sunday starts.
image from the table
AttrInfo = table
attr1 = column
4 = row
value = 2000

MySQL Select week number within current month

I have a table with events, some of which are recurring at spesific weeks within a month (Like, the 1st wednesday every month).
How would one select the below?
table
event day week
quiz wednesday 1
pseudocode would be:
SELECT * FROM table WHERE week = weeknumberWithinCurrentMonth()
Since we are now in the third week of february, 0 rows would be fetched from the above pseudoquery. If we were in week 1 of february, it would have selected the example row.
SELECT * FROM table WHERE week = FLOOR((DayOfMonth(NOW())-1)/7)+1
As close as you can get.
This may be what you are looking for:
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_week
SELECT WEEK(CURDATE()) - WEEK(DATE_FORMAT(NOW() , '%Y-%m-01')) + 1

How to get the count of specific days from week between a date range in mysql?

I have a table "task_table" containing columns-
Task_id, Start_date, End_date
And I have one more "configuration" table which has the records that tell which days of the week are working days.
This table has two columns -
week_day, isHoliday
and this table contains seven records as week_days are the Monday,Tuesday.....Sunday , and each record has an entry as 1 or 0. If a day is a holiday in any organization then there will be 0 against that day. Like if an organisation has holidays on Wednesday and Friday every week then there will be 0 against Wednesday and Friday only.
Now I want to make a SQL query to get the Task_id, Start_date, End_date, and the count of total days consumed on each task. (These days are the days between task start_date and end_date excluding the holiday days as configured in "configuration" table.)
I don't have time to fully answer this question now, but what I would do is:
Get the date as at the start of the Start_date week, and the date as at the end of the End_date week (you can get this by date_adding an amount of days according to the day of the week.
Then you want to date diff them, divide by seven, multiply by two, and remove any that you would have added (e.g. if the start date was Thursday then you'll need to remove one from the result, as you will have counted one for the Wednesday immediately prior.
I'll write the code out tomorrow (it's late here - something like 14 hours from now or so.) if noone else has suggested a better answer.
Edit: Right, didn't properly read the question, but the tactic still applies with a little fiddling. Speaking of which, here is the fiddle of my solution.
It boils down to the following code:
set #holidaysPerWeek = (select sum(isHoliday) from configuration);
select
Task_id,
((dateDiff(
DATE_ADD(End_Date, INTERVAL 7 - DayOfWeek(End_Date) DAY),
DATE_ADD(Start_Date, INTERVAL -DayOfWeek(Start_Date) + 1 Day)) + 1) / 7)
* #holidaysPerWeek
- (select sum(isHoliday) from configuration where week_day > DayOfWeek(End_Date))
- (select sum(isHoliday) from configuration where week_day < DayOfWeek(Start_Date)),
DayOfWeek(End_Date)
from task_table
This does exactly what I was saying before, but with a variable number of "weekends" spread throughout the week, by first selecting the number of holidays for if the full weeks were covered, then removing holidays that were before or after the start and end dates respectively.