SQL overlapping dates - sql

Here, we have many meetings during the day. Usually from 9:00am-11:30am, 1:00pm-3:30pm, 4:00pm-6:30pm.
I'm having a hard time scheduling these meetings. I don't get how to check if they overlap for the same person who is leading the meeting.
Ex:
Should raise an error if Person1 has a meeting scheduled for 10:00am- 11:00am and another for 10:45am-11:30am.
I've come to this solution, but it is only partially working:
if exists (
select 1
from
Meeting M
where
M.IdPerson = #IdPerson --Stored procedure parameter
and
(#StartDate <= M.EndDate or -- 1
#EndDate >= M.StartDate or -- 2
(#StartDate > M.StartDate and #DtFim < A.Data_Termino))) -- 3
return 1
In the image below, I explain the three conditions in the where clause. The green lines are the new meeting start and end dates. The red lines are the old's.
How can I make this work?

I think the logic you want is:
if exists (select 1
from Meeting M
where M.IdPerson = #IdPerson and --Stored procedure parameter
#StartDate <= M.EndDate and
#EndDate >= M.StartDate
)
return 1
(I'm not sure if you want <= or < for these comparisons.) This assumes that StartDate and EndDate also store the time component.
Two time periods overlaps if the first starts before the second ends, and it ends after the second starts.

Related

Returning date range of overlapping date ranges

I have a scenario where I have a SQL table that looks like the below screenshot. Is it possible to retrieve the start and end date of just the portion that overlaps between multiple records? I've reviewed similar questions from StackOverflow, and what I found was finding the records that has overlaps, but not the actual overlap range.
The desired result will show that the start date is 1/1/2017 and the end date is 6/30/2017 since that range is in both records.
Let's use variables to keep it simple. I assume you're using some join of two rows in your table where the ON condition determines that the dates overlap. But, since the part you're asking about is displaying the overlapping dates, we can just use variables:
DECLARE #start1 date = '20160701', #end1 date = '20170630'
,#start2 date = '20170101', #end2 date = '20171231'
SELECT CASE WHEN #start2 >= #start1 THEN #start2 ELSE #start1 END AS startdate
, CASE WHEN #end2 <= #end1 THEN #end2 ELSE #end1 END AS enddate
If you're on Azure SQL where GREATEST and LEAST are supported you can use:
SELECT GREATEST(#start1, #start2) AS startdate
, LEAST(#end1, #end2) AS enddate
The key is to understand the logic on the overlap.
if we are searching for the overlap period of many rows then it will ALWAYS start at the MAX(startDate).
the end point will be the minimum of the end dates where it is larger than our start date.
But we need to think about checking if they have an overlap period or not.
So the code should be:
declare #start datetime = (select MAX(PlanYearStart) start from #t);
if exists(select PlanYearEnd from #t where PlanYearEnd<#start)
begin
select null OverlapStart, null OverlapEnd;
return;
end;
select
#start OverlapStart,
MIN(PlanYearEnd) OverlapEnd
from #t;

Query to find out entries where dates don't overlap

Can anyone help me create a query which will populate a list of DJs who are not already booked in.
My user will select a start date (and time), and an end date (and time) - and then click a button to select a DJ.
I only want those DJs which are available between those time slots to appear in the list.
Here are the two tables which are involved
all I need in the listbox is the DJ Number, and the DJ Name
So far I have this... but it isn't working:
SELECT tblDJ.DJ_No AS [DJ ID], tblDJ.DJ_Name AS Name FROM tblDJ
WHERE (((tblDJ.[DJ_No]) Not In
(SELECT tblBooking.[FK_DJ_No]
FROM tblBooking
WHERE ( (tblBooking.End_Date) >= 01-04-2020 19:30:00 )))) ....etc....
I'm just entering a date in here for now, but obviously it will be stored in a variable once implemented.
Thanks
Implementing OVERLAPS of two intervals would look like:
1st_start_date <= 2nd_end_date and 1st_end_date >= 2nd_start_date
where 1st and 2nd values are markers of different events.
You could use that logic in combination with NOT EXISTS to discard those djs that are unavailable at a given time:
select dj_no, dj_name
from tbldj d
where not exists (
select 1
from tblbooking b
where b.fk_dj_no = d.dj_no
and b.start_date <= #END DATE#
and b.end_date >= #START DATE#
)
You just need to replace #START DATE# and #END DATE# with your values.
This does work because there are following assumptions:
Start date of the first event is prior to end date of that event
Start date of the second event is prior to end date of that event
Which seems logical, right?
The date in the SQL needs to be wrapped between two # in order for MS-Access to recognize it as a date:
select *
from tblDJ
where DJ_No not in
(
select FK_DJ_No
from tblBooking
where End_Date >= #2020-04-01 19:30:00#
)
Other than that you query will work.

How to use the average function with multiple conditional statements using SQL in Visual Studio SSRS 2008

I am trying to pull calculated data out of a SQL database using Visual Studio SSRS 2008. I am having problems trying to use conditionals in my select/from/where statements. One example of what I'm trying to do is to find the AVERAGE number of BTUs sold in a 24 hour period(from 10:00am yesterday to 10:00am today) from samples taken every 5 minutes. I'm reporting on a gas plant that has a gas flow value when running through a valve when it's open. Gas that flows through a particular open valve has a BTU value that I need to average. I have copied my current query below that has failures, but I think it's close to what it needs to be. The tagname that I want to average the value of is DTE_BTU if the other 2 tags mentioned below are > 0.
SET NOCOUNT ON
DECLARE #StartDate DateTime
DECLARE #EndDate DateTime
SET #StartDate = DateAdd(HOUR,-24,GetDate())
SET #EndDate = GetDate()
SET NOCOUNT OFF
SELECT case when temp.Value > 0 and temp2.value > 0 then AVG(Value where tagname ='DTE_BTU') end AS 'AvgDTEBTU'
From (
SELECT *
FROM History
WHERE History.TagName IN ('PGPOL_ProdVlv')
AND wwRetrievalMode = 'Cyclic'
AND wwCycleCount = 288
AND wwVersion = 'Latest'
AND DateTime >= #StartDate
AND DateTime <= #EndDate)as temp join
(SELECT * FROM History
WHERE History.TagName IN ('DTE_C_SCFM')
AND wwRetrievalMode = 'Cyclic'
AND wwCycleCount = 288
AND wwVersion = 'Latest'
AND DateTime >= #StartDate
AND DateTime <= #EndDate)as temp2 on temp.DateTime = temp2.DateTime
WHERE temp.StartDateTime >= #StartDate and temp2.StartDateTime >= #StartDate
Assuming I understand your information correctly, it seems like you really just need to see if the other two tags exist in the history table for that time period, so you don't necessarily need a case statement.
SELECT AVG(Value) as Avg_DTE_BTU
FROM History h
WHERE h.wwRetrievalMode = 'Cyclic'
AND h.wwCycleCount = 288
AND h.wwVersion = 'Latest'
AND h.DateTime >= #StartDate
AND h.DateTime <= #EndDate
AND h.tagname = 'DTE_BTU'
AND EXISTS
(
SELECT 1
FROM History x
WHERE x.wwRetrievalMode = 'Cyclic'
AND x.wwCycleCount = 288
AND x.wwVersion = 'Latest'
AND x.DateTime >= #StartDate
AND x.DateTime <= #EndDate
AND x.tagname = 'PGPOL_ProdVlv'
AND x.value > 0
)
AND EXISTS
(
SELECT 1
FROM History y
WHERE y.wwRetrievalMode = 'Cyclic'
AND y.wwCycleCount = 288
AND y.wwVersion = 'Latest'
AND y.DateTime >= #StartDate
AND y.DateTime <= #EndDate
AND y.tagname = 'DTE_C_SCFM'
AND y.value > 0
)
The above should take the average of all DTE_BTU values within the time range if there also exists the other two tag names in the time range and give you one row in return.
I dun know why "add Comment" is off here for me....
anyway friend...I can solve this problem as well but it's a little illogical way...
U know what...I think you could have used or created one table for every state and you used a table for every submit and then you put a FK from table for submitting to every tables related to your states.... I meant this :
you have Table "Submit" and also...
Table "PGPOL_ProdVlv" - Table "DTE_C_SCFM" - Table "DTE_BTU" ...I meant using one table for every state .infact I meant (1 : N) relation
Table "Submit"
1.NO
2.Time
3.and other columns
and then
Table "PGPOL_ProdVlv"
1.No
2.FK_NoSubmit
Table "DTE_C_SCFM"
1.No
2.FK_NoSubmit
and also other states like above as a table...
this could has made your query more simple and faster
as far as I got ...you are inserting these states in the same time...

SQL, Selecting between date/times

This is for (MS SQL Server 2008) It allows the user to schedule other users for a start and end date/time without overlaps.
I'm addressing the business rule of not being able to overlap individuals during a schedule. E.G, If user 1 is scheduled from 1/1/2012 to 1/4/2012, user 2 should not be able to submit a request for 1/2/2012 to 1/4/2012. This part is already taken care of, and here is my SQL.
SELECT * FROM fooTable
WHERE
Prim = 1
AND
Group = 10
AND
(('2012-06-01 08:01' between startdate and enddate
OR '2012-06-03 08:01' between startdate and enddate)
OR
('2012-06-01 08:01' < startdate) AND ('2012-06-03 8:01' > enddate))
I now have a requirement to allow a schedule to overlap in the sense that the new shift can begin as the last one ends. E.G, My end date is 1/1/2012 at 8:00pm - I should be able to schedule someone to start at 1/1/2012 and 8:00pm.
Need some help thinking this one through.
First off, don't use Group as a column name. It is a reserved word in every SQL standard. I renamed it to grp for the purpose of my answer.
Trying to schedule a new shift from '2012-06-01 08:00' to '2012-06-03 08:00' ...
INSERT INTO tbl (prim, grp, startdate, enddate)
SELECT 1, 10, '2012-06-01 08:00', '2012-06-03 08:00'
WHERE NOT EXISTS (
SELECT *
FROM tbl
WHERE prim = 1
AND grp = 10
AND '2012-06-03 08:00' > startdate -- not >= to allow sharing a border
AND '2012-06-01 08:00' < enddate -- and not BETWEEN ... AND either
)
Note that I compare:
new_end &gt old_start
new_start &lt old_end
If you use BETWEEN .. AND .. you include the borders of a shift in your test. It's the same as using >= and <=. You need to use > and < to allow borders to overlap.
Well, and try my largely simplified syntax. Not sure about what you had there originally.
Here is a working demo on sqlfiddle.com to play with.

T-SQL looping procedure

I have the following data:
ID Date interval interval_date tot_activity non-activity
22190 2011-09-27 00:00:00 1000 2011-09-27 10:00:00.000 265 15
I have another table with this data:
Date ID Start END sched_non_activity non_activity
10/3/2011 12:00:00 AM HBLV-22267 10/3/2011 2:02:00 PM 10/3/2011 2:11:00 PM 540
Now, in the second table's non_activity field, I would like this to be the value from the first table. However, I need to capture the tot_activity - non_activity where the intervals(in 15 min increments) from the first table, fall in the same time frame as the start and end of the second table.
I have tried setting variables and setting a loop where for each row it verifies the starttime by interval, but I have no idea how to return a variable with only one record, as I keep getting errors that my variable is getting too many results.
I have tried looking everywhere for tutorials and I can't find anything to help me out. Anyone have any pointers or tutorials on looping they could share?
You need to generate the interval end dates somehow; I'm assuming that there is always a record in the first table with a 15 minute interval record. In this case, an example would look like this:
;WITH Intervals
AS
(SELECT
Interval_date
,DATEADD(ms,840997,Interval_date) AS interval_end
,nonactivity
FROM A)
--Select query for Validation
--SELECT
-- b.[Date]
-- ,b.ID
-- ,b.Start
-- ,b.sched_non_activity
-- ,i.nonactivity
--FROM B
--JOIN Intervals AS i
--ON b.Start >= i.Interval_date
--AND b.[END] <= i.interval_end
UPDATE B
SET non_activity = i.nonactivity
FROM B
JOIN Intervals AS i
ON b.Start >= i.Interval_date
AND b.[END] <= i.interval_end
Obviously, you might need to tweak this depending on the exact circumstances.