I have to design a report which will be a list of a bunch of overlapping data from the same table.
I have to start with the Project table because for the report @ProjectId is the only thing you get as an anchor.
In the RessourceBookings table are all bookings and some are overlapping like
- Project A books resource B 24.01., 10 a.m. to 6 p.m.
- Project C books resource B 24.01., 11 a.m. to 1 p.m
- Project D books resource B 24.01., 1 p.m. to 4 p.m
These are the one I have to filter for and list all those booking conflicts for Project A.
This is the code I came up with at the moment. I didn't shorten it because I want to show that there are a few dependencies from some tables, which makes it a bit complicated (at least for me). If there are other parts besides the main problem which could be optimised, I would be happy to learn.
DECLARE @ProjectId INT = 8501
SELECT
p.Id AS 'Project-ID'
,p.Name AS 'Project-Name'
,p.Info AS 'Project-Info'
,pc.Name AS 'Project-Color'
,upr.DocumentName AS 'Project-Responsible'
,r.ResourceName AS 'Ressource-Name'
,r.Info AS 'Ressource-Info'
,CASE WHEN ugrr.ResourceRoleId IN (4,7)
THEN 0
ELSE 1
END AS 'Ressource-Availability'
,r.Quantity AS 'Booking-Quantity'
,rb.Start AS 'Booking-Start'
,rb.[End] AS 'Booking-End'
,pat.Name AS 'Booking-Action'
,rb.IsOption AS 'Booking-State'
,rb.OptionRequestAccepted AS 'Booking-Response'
,q2.ProjectId AS 'Conflict-Project-ID'
,q2.Name AS 'Conflict-Project-Name'
,q2.DocumentName AS 'Conflict-Project-Responsible'
,q2.Start AS 'Conflict-Start'
,q2.[End] AS 'Conflict-End'
,q2.IsOption AS 'Conflict-State'
FROM
Projects p
LEFT JOIN
ProjectColors pc ON pc.Id = p.ProjectColorId
LEFT JOIN
Users upr ON upr.Id = p.ResponsibleUserId
LEFT JOIN
ResourceBookings rb ON rb.ProjectId = p.Id
LEFT JOIN
Resources r ON r.Id = rb.ResourceId
LEFT JOIN
ProjectActions pa ON pa.Id = rb.ProjectActionId
LEFT JOIN
ProjectActionTypes pat ON pat.Id = pa.ProjectActionTypeId
LEFT JOIN
UserGroupResourceRoles ugrr ON ugrr.ResourceId = r.Id
LEFT JOIN
(SELECT
p2.ProjectId
,p2.Name
,upr2.DocumentName
,rb2.Start
,rb2.[End]
,rb2.IsOption
FROM
ResourceBookings rb2
LEFT JOIN
Projects p2 ON p2.Id = rb2.ProjectId
LEFT JOIN
Users upr2 ON upr2.Id = p2.ResponsibleUserId
WHERE
rb2.ResourceId = r.Id
AND (rb2.Start BETWEEN DATEADD(s, 1, rb.Start) AND DATEADD(s, -1, rb.[End])
OR rb2.[End] BETWEEN DATEADD(s, 1, rb.Start) AND DATEADD(s, -1, rb.[End])
OR DATEADD(s, 1,rb.Start) BETWEEN rb2.Start AND rb2.[End])) q2
WHERE
p.Id = @ProjectId
AND rb.Start >= SysDateTime()
AND ugrr.UserGroupId = 11
AND (SELECT Count(rb2.Id) - 1
FROM ResourceBookings rb2
WHERE rb2.ResourceId = r.Id
AND (rb2.Start BETWEEN DATEADD(s, 1, rb.Start) AND DATEADD(s, -1, rb.[End])
OR rb2.[End] BETWEEN DATEADD(s, 1, rb.Start) AND DATEADD(s, -1, rb.[End])
OR DATEADD(s, 1, rb.Start) BETWEEN rb2.Start AND rb2.[End])) > 0
My goal is something like:
| Project-ID | Project-Name | [...] | Conflict-Project-ID | Conflict-Project-Name | [...] |
|---|---|---|---|---|---|
| 1 | Project A | [...] | 2 | Project B | [...] |
| 1 | Project A | [...] | 3 | Project C | [...] |
| 1 | Project A | [...] | 4 | Project D | [...] |
Without the whole q2 parts, it works well to list all the information for Project A.
The errors are:
Wrong syntax near the WHERE-keyword.. Native error: 156. SQLSTATE: 42000. Severity 15. Msg State 1. Line 76.
Wrong syntax near ">".. Native error: 102. SQLSTATE: 42000. Severity 15. MsgState 1. Line 87.
Without the subquery join, it works well but I think I need that there. I've googled the last two days but can't find any solution. In my eyes it seems correct.
I can't change the tables or their content. I have to deal with the setup. So temporary tables are not an option (which maybe could help).
(But please no single-word technical-term-answers. I'm not a developer, I have just to work with these kind of things. I'm willing to learn but it's a bit hard without a professional background)
Edit: For clarifications, here is a picture of the table
ResourceBookings (top) and bottom the "goal" of the query if @ProjectId = 8525
CodePudding user response:
Try this
DECLARE @ProjectId INT = 8501
SELECT p.Id AS 'Project-ID'
,p.Name AS 'Project-Name'
,p.Info AS 'Project-Info'
,pc.Name AS 'Project-Color'
,upr.DocumentName AS 'Project-Responsible'
,r.ResourceName AS 'Ressource-Name'
,r.Info AS 'Ressource-Info'
,CASE WHEN ugrr.ResourceRoleId IN (4,7)
THEN 0
ELSE 1
END AS 'Ressource-Availability'
,r.Quantity AS 'Booking-Quantity'
,rb.Start AS 'Booking-Start'
,rb.[End] AS 'Booking-End'
,pat.Name AS 'Booking-Action'
,rb.IsOption AS 'Booking-State'
,rb.OptionRequestAccepted AS 'Booking-Response'
,q2.ProjectId AS 'Conflict-Project-ID'
,q2.Name AS 'Conflict-Project-Name'
,q2.DocumentName AS 'Conflict-Project-Responsible'
,q2.Start AS 'Conflict-Start'
,q2.[End] AS 'Conflict-End'
,q2.IsOption AS 'Conflict-State'
FROM Projects p
LEFT JOIN ProjectColors pc ON pc.Id = p.ProjectColorId
LEFT JOIN Users upr ON upr.Id = p.ResponsibleUserId
LEFT JOIN ResourceBookings rb ON rb.ProjectId = p.Id
LEFT JOIN Resources r ON r.Id = rb.ResourceId
LEFT JOIN ProjectActions pa ON pa.Id = rb.ProjectActionId
LEFT JOIN ProjectActionTypes pat ON pat.Id = pa.ProjectActionTypeId
LEFT JOIN UserGroupResourceRoles ugrr ON ugrr.ResourceId = r.Id
LEFT JOIN (SELECT p2.Id as id2
,p2.Name
,upr2.DocumentName
,rb2.Start
,rb2.[End]
,rb2.IsOption
,rb2.id
,rb2.ProjectId as rb_pid
,count(rb2.id) as id_count
FROM ResourceBookings rb2
LEFT JOIN Projects p2 ON p2.Id = rb2.ProjectId
LEFT JOIN Users upr2 ON upr2.Id = p2.ResponsibleUserId
LEFT JOIN Resources r ON r.Id = rb2.ResourceId
WHERE rb2.ResourceId = r.Id
AND (
rb2.Start BETWEEN DateAdd(s, 1,rb2.Start) AND DateAdd(s,-1,rb2.[End])
OR rb2.[End] BETWEEN DateAdd(s, 1,rb2.Start) AND DateAdd(s,-1,rb2.[End])
OR DateAdd(s, 1,rb2.Start) BETWEEN rb2.Start AND rb2.[End]
)
group by p2.Id
,p2.Name
,upr2.DocumentName
,rb2.Start
,rb2.[End]
,rb2.IsOption
,rb2.id
,rb2.ProjectId
) q2
on q2.rb_pid = p.Id
WHERE p.Id = @ProjectId
AND rb.Start >= SysDateTime()
AND ugrr.UserGroupId = 11
AND q2.id_count > 1
CodePudding user response:
Well tried far longer and it seems I was overcomplicating things with the subqeury.
Without it and with a few more Joins it works like a charm.
For clarifing why I "ignored" some of the tips I got:
INNERwasn't the right choice. It would mess with the results badly (probably because the tables aren't great designed and have many overlapping headers without correlation...)[]instead of''will probably the better choice after reading a bit more about it. Will fix that in the future in my querys.- The
window functionsseems powerfull and less resource-hungry and I will look into it but at this point I didn't fully understand them well enough.
I think I will try to optimise it again after reading ad understanding more about the named tipps but for now this works for me:
DECLARE @ProjectId INT = 6290
SELECT
p.Id AS 'Project-ID'
,p.Name AS 'Project-Name'
,p.Info AS 'Project-Info'
,pc.Name AS 'Project-Color'
,upr.DocumentName AS 'Project-Responsible'
,r.ResourceName AS 'Resource-Name'
,r.Info AS 'Resource-Info'
,CASE WHEN ugrr.ResourceRoleId IN (4,7)
THEN 0
ELSE 1
END AS 'Resource-Availability'
,rb.Quantity AS 'Booking-Quantity'
,rb.Start AS 'Booking-Start'
,rb.[End] AS 'Booking-End'
,pat.Name AS 'Booking-Action'
,rb.IsOption AS 'Booking-State'
,rb.OptionRequestAccepted AS 'Booking-Response'
,rb2.ProjectId AS 'Conflict-Project-ID'
,p2.Name AS 'Conflict-Project-Name'
,pc2.Name AS 'Conflict-Project-Color'
,upr2.DocumentName AS 'Conflict-Project-Responsible'
,rb2.Start AS 'Conflict-Start'
,rb2.[End] AS 'Conflict-End'
,pat2.Name AS 'Conflict-Booking-Action'
,rb2.IsOption AS 'Conflict-Booking-State'
,rb2.Quantity AS 'Conflict-Booking-Quantity'
FROM Projects p
LEFT JOIN ProjectColors pc ON pc.Id = p.ProjectColorId
LEFT JOIN Users upr ON upr.Id = p.ResponsibleUserId
LEFT JOIN ResourceBookings rb ON rb.ProjectId = p.Id
LEFT JOIN Resources r ON r.Id = rb.ResourceId
LEFT JOIN ProjectActions pa ON pa.Id = rb.ProjectActionId
LEFT JOIN ProjectActionTypes pat ON pat.Id = pa.ProjectActionTypeId
LEFT JOIN UserGroupResourceRoles ugrr ON ugrr.ResourceId = r.Id
/* Doubles for Conflicts */
LEFT JOIN ResourceBookings rb2 ON rb2.ResourceId = rb.ResourceId
LEFT JOIN Projects p2 ON p2.Id = rb2.ProjectId
LEFT JOIN ProjectColors pc2 ON pc2.Id = p2.ProjectColorId
LEFT JOIN ProjectActions pa2 ON pa2.Id = rb2.ProjectActionId
LEFT JOIN ProjectActionTypes pat2 ON pat2.Id = pa2.ProjectActionTypeId
LEFT JOIN Users upr2 ON upr2.Id = p2.ResponsibleUserId
WHERE
p.Id = @ProjectId
AND rb.Start >= SysDateTime()
AND ugrr.UserGroupId = 11
AND rb.Id <> rb2.Id
AND (
(
rb2.Start >= rb.Start
AND rb2.Start <= rb.[End]
)
OR
(
rb2.[End] >= rb.Start
AND rb2.[End] <= rb.[End]
)
OR
(
rb.Start >= rb2.Start
AND rb.Start <= rb2.[End]
)
)

