Im trying to create a specific query.
E.g
i have table with events:
id | start | end
-----------------------------------------
1 | 10-08-2013 12:00 | 10-08-2013 14:00
2 | 10-08-2013 12:00 | 10-08-2013 14:00
3 | 10-08-2013 15:00 | 10-08-2013 16:00
And i want to insert a new event( start: 13:00, end: 15:30 ) and before that i want to check by query how many events are on the same time. In this case results should be 3: beacause 2 events are in start time and one is on the end time.
Thanks.
The correct logic for overlap is:
where new_startDate <= end and
new_endDate >= start
give this a try,
SELECT COUNT(DISTINCT ID) totalCOunt
FROM tableName
WHERE new_startDate BETWEEN start AND end
OR
new_endDate BETWEEN start AND end
where new_startDate and new_endDate are the new dates of the event.
Related
Is there a way to select or query the data only on working hours?
id
description
datetime
1
Alarm Activated
2022-01-02 14:00:00
2
Alarm Deactivated
2022-01-02 15:00:00
3
Alarm Activated
2022-01-03 18:00:00
..
Alarm Activated
2022-01-31 11:00:00
I'd like to get the number of the alarm activated on or during working hours from mon-fri 8am to 5pm.
I tried to use the between date but no luck.
SELECT * -- if you need to count them only - use SELECT COUNT(*)
FROM datatable
WHERE WEEKDAY(`datetime`) < 5 -- test weekday
AND TIME(`datetime`) BETWEEN '08:00:00' AND '17:00:00'; -- test hours
Here we use the following tests:
weekday < 6 (Saturday) = Monday to Friday
hour more than 7 (from 08:00:00)
hour less than 17 (to 16:59:59)
create table alarms(
id int,
description varchar(100),
date_time datetime);
insert into alarms values
(1,'Alarm Activated',
'2022-01-02 14:00:00'),
(2,'Alarm Deactivated',
'2022-01-02 15:00:00'),
(3,'Alarm Activated',
'2022-01-03 18:00:00'),
(4,'Alarm Activated',
'2022-01-31 11:00:00');
select *
from alarms
where weekday(date_time) < 6
and 7 < hour(date_time) < 17;
id | description | date_time
-: | :-------------- | :------------------
3 | Alarm Activated | 2022-01-03 18:00:00
4 | Alarm Activated | 2022-01-31 11:00:00
db<>fiddle here
Is there a way in MySQL to select specific columns based on dates entered as variables?
For example, if there is a table containing daily data from Day 1 to Day 31 for various items. Like the table below -
id
Month
Year
Item
Day 1
Day 2
Day3
Day 4
Day 5
1
December
2021
Bag
2
4
2
5
1
2
December
2021
Pencil
3
5
1
8
2
This goes up to Day 31 if needed for any number of items in the month.
I'd like to be able to enter a date range such as 2021-12-01 and 2021-12-03 along with the item name 'Bag' and get the sum of the values in that data range - 2+4+2 = 8.
Is this possible?
And if it isn't possible with this current method I'm attempting, is there a way to get it done?
Thanks.
This may not be the answer you want, but you should seriously fix your data model. Do not store your dates as columns, but rather store each date's data point in a separate record. So the first record from your sample table would become:
id | Item | Date | num_items
1 | Bag | 2021-12-01 | 2
1 | Bag | 2021-12-02 | 4
1 | Bag | 2021-12-03 | 2
1 | Bag | 2021-12-04 | 5
1 | Bag | 2021-12-05 | 1
Now your query becomes much more tractable:
SELECT id, Item, SUM(num_items) AS total
FROM yourTable
WHERE Date BETWEEN '2021-12-01' AND '2021-12-03' AND Item = 'Bag'
GROUP BY id, Item;
a bit verbose, but you can do something like this :
SELECT
IF (DAY('2021-12-01') <= 1 AND DAY('2021-12-03') >= 1, day1, 0)
+ IF (DAY('2021-12-01') <= 2 AND DAY('2021-12-03') >= 2, day2, 0)
+ IF (DAY('2021-12-01') <= 3 AND DAY('2021-12-03') >= 3, day3, 0)
+ ...
Although it's probably better to change your data model to have a date and value as column.
I have a table that displays shift start time, break 01 start time, break 01 end time, lunch start time, lunch end time, break 02 start time, break 02 end time,
shift end time.
Here I wanted to calculate everything in minutes.
Time = TotalShiftTime - ((break01Start - break01endtime) + (lunchstart - lunchend) + (break02start - break02end))
I want to calculate this in minutes on daily basis. I want to calculate this with respect to start date and end date which i wanted to give as input.
It has to be like
[(endDate - startDate) * Time]
If my endDate is 07/03/2018 and startDate is 04/03/2018 I want it to be [3 * Time].
PS: I don't have a column for startDate and endDate. I want to get cumulative minutes when I select system date.
How can I achieve this?
Shiftstart | Brk01start | Brk01end | LunchStart | LunchEnd | Brk02Start | Brk02end | Shiftend
8:00:00 | 11:15:00 | 11:45:00 | 13:00:00 | 13:30:00 | 15:15:00 | 15:30:00 | 17:00:00
I have a table like this:
id | date | time from | time to
1 | 2015-09-19 | 20:00 | 04:00
2 | 2015-09-19 | 10:00 | 23:00
3 | 2015-09-19 | 22:00 | 10:00
4 | 2015-09-20 | 10:00 | 16:00
For each row, I need hour between 22:00 and 06:00
Then first row has 6, second row has 1, third row has 8, fourth row has nothing.
Yes, it is possible. Just use some logic:
If time to is lower than time from then just use the amount of hours between midnight and time from but maximum 2 hours, and add the minimum between 6 hours (the max limit) and time to.
In time from is lower than time to then
-- if time from is greater than 6 add 0, else add time from
-- if time to is lower than 22 add 0, else add difference between 24 and time to.
SELECT
*,
CASE
WHEN time_to < time_from
THEN
TIME_TO_SEC (
LEAST(TIMEDIFF(TIME('24:00'), time_from), TIME('02:00')) +
LEAST(time_to, TIME('06:00'))
) / 60 / 60
ELSE
TIME_TO_SEC (
CASE WHEN time_from > TIME('06:00') THEN TIME('00:00') ELSE time_from END +
CASE WHEN time_to < TIME('22:00') THEN TIME('00:00') ELSE TIMEDIFF(TIME('24:00'), time_to) END
) / 60 / 60
END new_time_to
FROM demo;
Here is the example: http://sqlfiddle.com/#!9/78571/36/0
I got an alert table for users, in which we have to send alerts to users in user defined intervals like 0 ( only once), 3 months, 6 months, 1 year
So I designed a table like this
id | user_id | alert_date | repeat_int
-----+--------------+-------------------------+-------------
12 | 747 | 2013-04-19 00:00:00 | 0
13 | 746 | 2013-03-19 00:00:00 | 1
14 | 745 | 2012-04-19 00:00:00 | 0
15 | 744 | 2013-04-19 00:00:00 | 0
16 | 743 | 2013-05-19 00:00:00 | 0
We are sending alert just a day before "alert_date"
With the following query I can fetch the data
SELECT al.id,
al.user_id,
al.alert_date,
al.repeat_int AS repunit
FROM alerts AS al
WHERE DATE_ADD(alert_date,INTERVAL repeat_int MONTH)=date_add(CURRENT_DATE,INTERVAL 1 DAY)
OR date(al.alert_date)=date_add(CURRENT_DATE,INTERVAL 1 DAY)
Its working file but my real problem is
The repeat will only works once, we need it repeat every interval
ie. If alert date is 2012-03-14 and repeat_int is 0 - Need to work only once
but if alert date is 2012-03-14 and repeat_int is 1 - Need to work in every 14th from 2012-03-14
and if the alert date is 2012-03-14 and repeat_int is 3 - Need to work in every three month's 14. ie alert on 2012-03-14, 2012-06-14, 2012-09-14 etc...
Is there any way to do that?
Update
The OP has changed his schema in response to comments, so the query is essentially:
SELECT *
FROM alerts
WHERE CURRENT_DATE + INTERVAL 1 DAY = COALESCE(next_alert_date, alert_date);
This handles "next_alert_date" being NULL on the very first run.
Original answer
For the original schema:
SELECT *
FROM alerts
JOIN (SELECT CURRENT_DATE + INTERVAL 1 DAY AS tomorrow) d
WHERE -- We want to alert if
-- 1. Tomorrow is the alert_date
tomorrow = alert_date
OR
--
-- 2. Tomorrow is "repeat_int" months removed from alert_date, falling on
-- the same day of the month or on the end of the month if the original
-- alert_date day of month is later in the month than is possible for us
-- now. E.g., 2013-01-31 repeated monthly is adjusted to 2013-02-28.
(
PERIOD_DIFF(DATE_FORMAT(tomorrow, '%Y%m'), DATE_FORMAT(alert_date, '%Y%m'))
MOD repeat_int = 0
AND
-- Make sure we are at the same day of the month
( (DAYOFMONTH(tomorrow) = DAYOFMONTH(alert_date)
OR
-- Or, if the day of the alert is beyond the last day of our month,
-- that we are at the end of our month.
(LAST_DAY(alert_date) > LAST_DAY(tomorrow)
AND
DAYOFMONTH(tomorrow) = LAST_DAY(tomorrow)) )
);