Query to find out entries where dates don't overlap - sql

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.

Related

Getting Average(DateDiff) based on Multiple Instances of a Groupby Field

Currently I'm trying to grab the average date difference between the start and end datetime of multiple events which occur multiple times within the same month. There are four different types of Event which run for different amounts of time.
select
min(datetime) starttime,
max(datetime) endtime,
avg(endtime - min(datetime)) As avg_days,
event
from log_economy_event_point_spending a
AND datetime between '2021-01-01' AND '2021-04-30'
group by event
order by event
However, using this method, if the event occurs multiple times it takes the start of the first event, and the end of the last event. How do I write SQL code that can get the average datetime duration of different type of event?
Many thanks
Hmmm . . . I think you want:
select event,
min(datetime) as starttime, max(datetime) as endtime,
(max(datetime) - min(datetime)) / nullif(count(*) - 1, 0) As avg_days
from log_economy_event_point_spending leeps
where datetime >= '2021-01-01' and
datetime < '2021-05-01'
group by event
order by event;
This fixes the date/time arithmetic to get the average. Note the other changes:
The date comparison includes all date/time values in April, which I'm guessing is your intention. Your version eliminates values on April 30th.
The table aliases is meaningful rather than being an arbitrary letter.
You cannot re-use column aliases in the expressions in the select where the aliases are defined.

How to get all dates that they have at least one Event on that day from a given date range?

I am having a SQLite database which contains a table Events with start and end dates. I would like to get a Set (could be an array without duplicates) of dates that they at least have an Event on that day let's say from 1st of August to 20th of August.
Let's take some example events:
Event 1 from 02.08.2016 to 07.08.2016
Event 2 from 10.08.2016 to 12.08.2016
Event 3 from 11.08.2016 to 15.08.2016
Then the outcome should be:
[02.08.2016, 03.08.2016, 04.08.2016, 05.08.2016, 06.08.2016, 07.08.2016, 10.08.2016, 11.08.2016, 12.08.2016, 13.08.2016, 14.08.2016, 15.08.2016]
where 11.08.2016 and 12.08.2016 are not repeating.
NB: I am expecting an answer that could solve this problem only using SQL rather combining some programming code. I need that on a mobile device (iOS) where I am trying to optimize the user experience and performance.
Here is an example of creating a date table with recursive CTE and using it to select dates you need:
WITH RECURSIVE
cnt(dt) AS
(
SELECT MIN(startDate) FROM Events
UNION ALL
SELECT date(dt,'+1 day') FROM cnt
WHERE dt < (SELECT MAX(endDate) FROM Events)
LIMIT 10000
)
SELECT DISTINCT dt
FROM cnt
JOIN Events ON dt BETWEEN startDate AND endDate
ORDER BY dt;
SQL fiddle demo

how do i get my customer records to still appear in the table beyond the 5 days advance period

I have a query that pull out all customers records I will need to call within the next 5 days in the where clause as:
Remind to call =< DATEADD(DD,5,GETDATE() and
Remind to call >= GETDATE()
The way i want it to work is that i want all customers records that i need to call 5 days in advance from GETDATE(). Once it has entered the table, it needs to stay in the table until users enters a date for the 'Confirmstart' field on web application.
What happens is my query displays the data as it should except it removes the customers record after the 5 days where i want the records to remain until the user has entered a date for the 'ConfirmStart' field
For example - Lets say todays date is 03/08/2016 where I want to pull out the customers i need to call within the next 5 days, therefore in my where clause i wrote:
<Remind to call =< DATEADD(DD,5,GETDATE() and
<Remind to call >= GETDATE()
The Dateadd should pull out records up to 08/08/2016. t also say record iD called 'CR1' that has a RemindToCall date 08/08/2013 meet this criteria.
The 'CR1' record appears in the table which is great. However when GETDATE() reaches the 9/08/2016, the 'CR1' record disappears from the table when i want it to still remain in that table until the 'ConfirmedStart' date is entered.
How do i get my customer records to still appear in the table beyond the 5 days advance period even though i need the records to appear 5 days in advance?
Further Information:
To elaborate on my above example - here is the SQL code that for the 'CR1' record but instead of it being named 'CR1' in this live example its CoS ID record called'1232' - everything else remains the same:
SELECT
CoSID,
SurName,
FirstName,
EmailAddress,
CONVERT (varchar,UKAddressDeadline,103) as UKAddressDeadline,
CONVERT (varchar,PlacementStart,103) as PlacementStart,
CONVERT (varchar,PlacementEnd,103) as PlacementEnd,
CONVERT (varchar,RemindToCall,103) as RemindToCall,
ExtReference,
HostOrgName,
UKEndorsement,
PaymentUKBA
FROM
dbo.tbl_CoS
WHERE
RemindToCall between CAST('2016-08-03' AS DATE) and DateAdd(DD,+5, CAST('2016-08-03' AS DATE)) AND
(CoSNotRequired is null and
AppWithdrawn = 0 and
CoSWithdrawn = 0 and
VisaRejected = 0 and
UKAddressDeadline is not null AND
ConfirmedStart is NULL OR
UKEndorsement is NULL)
SQL RESULT of above
I hope this extra information/details help you.
Thanks people :D
assuming that the Confirmstart is null when no value are entered.
Add that to your where clause
WHERE
(
(
[Remind to call] =< DATEADD(DD,5,GETDATE() and
[Remind to call] >= GETDATE()
)
OR
(
Confirmstart IS NULL
)
)
Maybe you need something like this:
([Remind to call] =< DATEADD(DD,5,GETDATE() and
[Remind to call] > CONVERT(varchar(8), GETDATE(), 112)) or
ConfirmStart is Null
In other words, you have to pass in the second line not GetDate(), but 08/08/2016 00:00:00

Latest date and time in SQL without ORDER BY

I'm trying to find a way to display the last event held (last date and time) in an events table whilst displaying all the columns for that event without using ORDER BY.
For example:
SELECT * from Events
where dateheld in (select max(dateheld) from events)
AND starttime in (select max(starttime) from events)
When I put MAX starttime, it displays nothing. When I put MIN starttime it works but displays the earliest time of that date and not the latest.
I guess you could print out your records, throw them down the stairs, and the ones that go farthest have the "lightest" dates. You cannot sort without order by. It's like wanting water that isn't wet. Unless your data naturally comes out in the order you want, you MUST sort.
Of course, if you want only the record that has the absolute most recent date, and don't need more than just that one record, then
SELECT yourdatetimefield, ...
FROM yourtable
HAVING yourdatetimefield = MAX(yourdatetimefield)
If you are only looking for the latest item:
EDIT gets a little more complicated when you have seperate date and time fields, but this should work. This is a ridiculous kludge for a situation where date and time should be stored in one field.
SELECT *
FROM (
SELECT *
FROM Events
WHERE dateTime = (SELECT MAX(dateheld) FROM Events)
) temp
WHERE starttime = (SELECT MAX(starttime) FROM (
SELECT *
FROM Events
WHERE dateTime = (SELECT MAX(dateheld) FROM Events)
) temp 2 )

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.