How to join 4 tables based on PK column? - sql

In my stored procedure I have four select queries. These queries have a single column JobDescriptionCode common in them. I want to join these tables on that column.
This is my stored procedure :
SELECT a.JobDescriptionCode, ISNULL(a.ApprovedCount,0) - ISNULL(b.ApprovedCount,0) AS StructureChange
FROM
(select rh.JobDescriptionCode, SUM(ApprovedCount) as ApprovedCount from RequisitionHistory rh
left join OGJobDescription jd on rh.JobDescriptionCode = jd.JobDescriptionCode
where Convert(varchar(8),rh.CreationDate,1) between #PreviousMonthStartDate and #PreviousMonthEndDate
GROUP by rh.JobDescriptionCode) a
INNER JOIN
(select rh.JobDescriptionCode, SUM(ApprovedCount) as ApprovedCount from RequisitionHistory rh
left join OGJobDescription jd on rh.JobDescriptionCode = jd.JobDescriptionCode
where Convert(varchar(8),rh.CreationDate,1) between #startDate and #endDate
GROUP by rh.JobDescriptionCode) b
on a.JobDescriptionCode = b.JobDescriptionCode
select r.JobDescriptionCode, count(*) as NewJoining from CandidateHistory ch
left join Requisition r on ch.RequisitionCode = r.RequisitionCode
where ch.StatusCode = 6005 and Convert(varchar(8),ch.CreationDate,1) between #startDate and #endDate
GROUP BY r.JobDescriptionCode
select r.JobDescriptionCode, count(*) as Separation from CandidateHistory ch
left join Requisition r on ch.RequisitionCode = r.RequisitionCode
where ch.StatusCode = 10005 and Convert(varchar(8),ch.CreationDate,1) between #startDate and #endDate
GROUP BY r.JobDescriptionCode
SELECT r.JobDescriptionCode, d.DepartmentName,jd.JobDescriptionName, SUM(r.ApprovedCount) as ApprovedCount, SUM(r.FilledCount) as FilledCount,
SUM(r.UnfilledCount) as UnfilledCount from Requisition r
left join OGJobDescription jd on r.JobDescriptionCode = jd.JobDescriptionCode
left join OGDepartment d on r.DepartmentCode = d.DepartmentCode
where Convert(varchar(8),r.RequisitionDate,1) between #startDate and #endDate
GROUP BY jd.JobDescriptionName, d.DepartmentName, r.JobDescriptionCode
Now dates are passed as a parameter to the SP and are based on 1 month. Now some queries return 2 rows, some 10 and so on. I just want to match the PK JobDescriptionCode and on that, join the tables.
Is it possible, if so how?

You can treat every separate query as a subquery and join them together like this:
SELECT q1.JobDescriptionCode, StructureChange, NewJoining, Separation, DepartmentName, JobDescriptionName, ApprovedCOUNT, FilledCOUNT, UnfilledCOUNT
FROM (
SELECT
a.JobDescriptionCode,
ISNULL(a.ApprovedCOUNT,0) - ISNULL(b.ApprovedCOUNT,0) AS StructureChange
FROM (
SELECT rh.JobDescriptionCode, SUM(ApprovedCOUNT) AS ApprovedCOUNT
FROM RequisitionHistory rh
LEFT JOIN OGJobDescription jd ON rh.JobDescriptionCode = jd.JobDescriptionCode
WHERE CONVERT(VARCHAR(8),rh.CreationDate,1) BETWEEN #PreviousMonthStartDate AND #PreviousMonthEndDate
GROUP BY rh.JobDescriptionCode
) a
INNER JOIN (
SELECT rh.JobDescriptionCode, SUM(ApprovedCOUNT) AS ApprovedCOUNT
FROM RequisitionHistory rh
LEFT JOIN OGJobDescription jd ON rh.JobDescriptionCode = jd.JobDescriptionCode
WHERE CONVERT(VARCHAR(8),rh.CreationDate,1) BETWEEN #startDate AND #endDate
GROUP BY rh.JobDescriptionCode
) b ON a.JobDescriptionCode = b.JobDescriptionCode
) q1
INNER JOIN (
SELECT r.JobDescriptionCode, COUNT(*) AS NewJoining
FROM CANDidateHistory ch
LEFT JOIN Requisition r ON ch.RequisitionCode = r.RequisitionCode
WHERE ch.StatusCode = 6005 AND CONVERT(VARCHAR(8),ch.CreationDate,1) BETWEEN #startDate AND #endDate
GROUP BY r.JobDescriptionCode
) q2 ON q1.JobDescriptionCode = q2.JobDescriptionCode
INNER JOIN (
SELECT r.JobDescriptionCode, COUNT(*) AS Separation
FROM CANDidateHistory ch
LEFT JOIN Requisition r ON ch.RequisitionCode = r.RequisitionCode
WHERE ch.StatusCode = 10005 AND CONVERT(VARCHAR(8),ch.CreationDate,1) BETWEEN #startDate AND #endDate
GROUP BY r.JobDescriptionCode
) q3 ON q1.JobDescriptionCode = q3.JobDescriptionCode
INNER JOIN (
SELECT
r.JobDescriptionCode,
d.DepartmentName,
jd.JobDescriptionName,
SUM(r.ApprovedCOUNT) AS ApprovedCOUNT,
SUM(r.FilledCOUNT) AS FilledCOUNT,
SUM(r.UnfilledCOUNT) AS UnfilledCOUNT
FROM Requisition r
LEFT JOIN OGJobDescription jd ON r.JobDescriptionCode = jd.JobDescriptionCode
LEFT JOIN OGDepartment d ON r.DepartmentCode = d.DepartmentCode
WHERE CONVERT(VARCHAR(8),r.RequisitionDate,1) BETWEEN #startDate AND #endDate
GROUP BY jd.JobDescriptionName, d.DepartmentName, r.JobDescriptionCode
) q4 ON q1.JobDescriptionCode = q4.JobDescriptionCode
After looking a little at your queries I think it could be simplified a bit, will look a little more.
Edit: I think this query should be equivalent, but without test data it's a bit hard to confirm. If it produces the correct output it might perform better:
SELECT
q1.JobDescriptionCode,
q1.StructureChange,
q2.NewJoining,
q2.Separation,
q3.DepartmentName,
q3.JobDescriptionName,
q3.ApprovedCount,
q3.FilledCount,
q3.UnFilledCount
FROM (
SELECT rh.JobDescriptionCode,
SUM(CASE
WHEN CONVERT(VARCHAR(8),rh.CreationDate,1) BETWEEN #startDate AND #endDate THEN -ApprovedCount
WHEN CONVERT(VARCHAR(8),rh.CreationDate,1) BETWEEN #PreviousMonthStartDate AND #PreviousMonthEndDate THEN ApprovedCount
END) AS StructureChange
FROM RequisitionHistory rh
LEFT JOIN OGJobDescription jd ON rh.JobDescriptionCode = jd.JobDescriptionCode
GROUP BY rh.JobDescriptionCode
) q1
INNER JOIN (
SELECT
r.JobDescriptionCode,
SUM(CASE WHEN ch.StatusCode = 6005 THEN 1 ELSE 0 END) AS NewJoining,
SUM(CASE WHEN ch.StatusCode = 10005 THEN 1 ELSE 0 END) AS Separation
FROM CandidateHistory ch
LEFT JOIN Requisition r ON ch.RequisitionCode = r.RequisitionCode
WHERE CONVERT(VARCHAR(8),ch.CreationDate,1) BETWEEN #startDate AND #endDate
GROUP BY r.JobDescriptionCode
) q2 ON q1.JobDescriptionCode = q2.JobDescriptionCode
INNER JOIN (
SELECT
r.JobDescriptionCode,
d.DepartmentName,
jd.JobDescriptionName,
SUM(r.ApprovedCount) AS ApprovedCount,
SUM(r.FilledCount) AS FilledCount,
SUM(r.UnFilledCount) AS UnFilledCount
FROM Requisition r
LEFT JOIN OGJobDescription jd ON r.JobDescriptionCode = jd.JobDescriptionCode
LEFT JOIN OGDepartment d ON r.DepartmentCode = d.DepartmentCode
WHERE CONVERT(VARCHAR(8),r.RequisitionDate,1) BETWEEN #startDate AND #endDate
GROUP BY jd.JobDescriptionName, d.DepartmentName, r.JobDescriptionCode
) q3 ON q1.JobDescriptionCode = q3.JobDescriptionCode

Try putting all your queries into WITH like this:
WITH table_alias1 AS (
SELECT ...
),
table_alias2 AS (
SELECT .. ),
table_alias3 AS (
SELECT .. ),
table_alias4 AS (
SELECT .. )
SELECT * FROM
table_alias1 t1 INNER JOIN
table_alias2 t2 ON t1.JobDescriptionCode = t2.JobDescriptionCode INNER JOIN
table_alias2 t3 ON t1.JobDescriptionCode = t3.JobDescriptionCode INNER JOIN
table_alias2 t4 ON t1.JobDescriptionCode = t4.JobDescriptionCode;
Your queries are massive, so I did not put them here for readability reasons.

Related

How to make ledger query using SELECT statement in SQL

DECLARE #AccountId int = 1152;
DECLARE #StartDate datetime = '10/1/2019';
DECLARE #EndDate datetime = '1/25/2020';
DECLARE #PreBalance int = (SELECT ISNULL(SUM(Debit), 0) - ISNULL(SUM(Credit), 0)
FROM GL_Voucher m
INNER JOIN GL_Voucher_Item_Type d ON m.Id = d.GL_Voucher_Id
WHERE m.Date < #StartDate
AND d.L5_Id = #AccountId)
SELECT d.Date, d.debit AS Debit, d.Credit, #PreBalance AS Opening
FROM GL_Voucher_Item_Type d
INNER JOIN GL_Voucher m ON d.GL_Voucher_Id = m.Id
INNER JOIN Level5 a ON d.L5_Id = a.Id
INNER JOIN Level4 l4 ON a.L4_Id = l4.Id
INNER JOIN Level3 l3 ON l4.L3_id = l3.Id
INNER JOIN Level2 l2 ON l3.L2_id = l2.Id
INNER JOIN Level1 l1 ON l2.L1_id = l1.Id
WHERE m.Date BETWEEN #StartDate AND #EndDate
AND d.L5_Id = #AccountId
ORDER BY Date ASC
This is the output of query
I want to show balance column initially as Balance=#Prebalance tehn if credit then Balance=Balance-Credit and if debit then Balance=Balance+Debit
I'd calculate running totals of debits and credits using SUM OVER, then do the math.
This is untested, but should be pretty close to what you're looking for.
SELECT d.DATE
,d.debit AS Debit
,d.Credit
,#PreBalance
- SUM(d.debit) OVER (ORDER BY d.DATE) + SUM(d.Credit) OVER (ORDER BY d.DATE)
AS Opening
FROM GL_Voucher_Item_Type d
INNER JOIN GL_Voucher m ON d.GL_Voucher_Id = m.Id
INNER JOIN Level5 a ON d.L5_Id = a.Id
INNER JOIN Level4 l4 ON a.L4_Id = l4.Id
INNER JOIN Level3 l3 ON l4.L3_id = l3.Id
INNER JOIN Level2 l2 ON l3.L2_id = l2.Id
INNER JOIN Level1 l1 ON l2.L1_id = l1.Id
WHERE m.DATE BETWEEN #StartDate
AND #EndDate
AND d.L5_Id = #AccountId
ORDER BY DATE ASC
Please try this:
select d.Date,#PreBalance as Balance,
case when d.Credit > 0 THEN #PreBalance - d.Credit
else debit+#PreBalance end as CreditOrDebitBalance
from GL_Voucher_Item_Type d
INNER JOIN GL_Voucher m ON d.GL_Voucher_Id=m.Id
INNER JOIN Level5 a ON d.L5_Id=a.Id
INNER JOIN Level4 l4 ON a.L4_Id=l4.Id
INNER JOIN Level3 l3 ON l4.L3_id=l3.Id
INNER JOIN Level2 l2 ON l3.L2_id=l2.Id
INNER JOIN Level1 l1 ON l2.L1_id=l1.Id
WHERE m.Date BETWEEN #StartDate AND #EndDate
AND d.L5_Id=#AccountId
ORDER BY Date ASC
Please show us expected output so we can help further.

Adding weekdays to select statement

I have a select statement that pulls and consolidates data from multiple tables. I need to add additional logic to calculate the number of weekdays between the createdDt and CallEndDate (but if the callEndDate is null use the current date).
We are using SQL Server 2016 and am at a loss on how to incorporate this additional calculated logic with my select statement below. Any suggestions?
SELECT c.ID, c.CreatedDt, c.LastUpdatedDt, c.CALLSTARTDT, c.CALLENDDT, c.DUEDT,
c.TYPE, c.DESCRIPTION, c.COMMENT, c.CONTRACT, c.DISCLOSUREPTAN, c.DISCLOSURENPI, c.DISCLOSURETIN,
c.DISCLOSUREIVR, c.CALLERFIRSTNAME, c.CALLERLASTNAME, c.CALLERPHONE, c.CALLEREMAIL, c.STATUS,
c.STATUSQUALIFIER, c.RATING, u1.Name as LastUpdatedByName, u2.Name as CreatedByName,
u3.Name as OwnedByName, p.PTAN, p.NPI,p.NAME, con.LOB
FROM Case c
LEFT JOIN ossys_User u1 ON c.LastUpdatedBy = u1.Id
LEFT JOIN ossys_User u2 ON c.CreatedBy = u2.ID
LEFT JOIN ossys_User u3 ON c.OwnedBy = u3.Id
INNER JOIN PROVIDER p ON c.TargetId = p.Id
INNER JOIN CONTRACTS con ON p.Contract = con.Contract
WHERE
c.LastUpdatedDt BETWEEN '2019-01-01' AND '2019-07-01'
Order By c.CreatedDt ASC
Calculations can be included in your select statement as such:
SELECT c.ID, c.CreatedDt, c.LastUpdatedDt, c.CALLSTARTDT, c.CALLENDDT, c.DUEDT,
c.TYPE, c.DESCRIPTION, c.COMMENT, c.CONTRACT, c.DISCLOSUREPTAN,
c.DISCLOSURENPI,c.DISCLOSURETIN,c.DISCLOSUREIVR, c.CALLERFIRSTNAME, c.CALLERLASTNAME,
c.CALLERPHONE, c.CALLEREMAIL, c.STATUS, c.STATUSQUALIFIER, c.RATING,
u1.Name as LastUpdatedByName, u2.Name as CreatedByName,
u3.Name as OwnedByName,
p.PTAN, p.NPI,p.NAME,
con.LOB,
((DATEDIFF(dd, c.CreateDt, ISNULL(c.CALLENDDT,#GETDATE)) + 1)
-(DATEDIFF(wk, c.CreateDt, ISNULL(c.CALLENDDT,#GETDATE)) * 2)
-(CASE WHEN DATENAME(dw, c.CreateDt) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, ISNULL(c.CALLENDDT, #GETDATE)) = 'Saturday' THEN 1 ELSE 0 END))
As diff
FROM Case c
LEFT JOIN ossys_User u1 ON c.LastUpdatedBy = u1.Id
LEFT JOIN ossys_User u2 ON c.CreatedBy = u2.ID
LEFT JOIN ossys_User u3 ON c.OwnedBy = u3.Id
INNER JOIN PROVIDER p ON c.TargetId = p.Id
INNER JOIN CONTRACTS con ON p.Contract = con.Contract
WHERE
c.LastUpdatedDt BETWEEN '2019-01-01' AND '2019-07-01'
Order By c.CreatedDt ASC
Although I would more likely go with the solution defined by the link posted by #openshac and put that into a function before calling as such.
CREATE FUNCTION [dbo].fn_CountWeekDays
(
#fromdate Datetime,
#todate Datetime
)
RETURNS TABLE AS RETURN
(
SELECT
(DATEDIFF(dd, #fromdate, #todate) + 1)
-(DATEDIFF(wk, #fromdate, #todate) * 2)
-(CASE WHEN DATENAME(dw, #fromdate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #todate) = 'Saturday' THEN 1 ELSE 0 END)
As NoOfWeekDays
)
GO
SELECT c.ID, c.CreatedDt, c.LastUpdatedDt, c.CALLSTARTDT, c.CALLENDDT, c.DUEDT,
c.TYPE, c.DESCRIPTION, c.COMMENT, c.CONTRACT, c.DISCLOSUREPTAN,
c.DISCLOSURENPI,c.DISCLOSURETIN,c.DISCLOSUREIVR, c.CALLERFIRSTNAME, c.CALLERLASTNAME,
c.CALLERPHONE, c.CALLEREMAIL, c.STATUS, c.STATUSQUALIFIER, c.RATING,
u1.Name as LastUpdatedByName, u2.Name as CreatedByName,
u3.Name as OwnedByName,
p.PTAN, p.NPI,p.NAME,
con.LOB,
CountWeekDays(c.CreateDt, ISNULL(c.CALLENDDT,#GETDATE))
As diff
FROM Case c
LEFT JOIN ossys_User u1 ON c.LastUpdatedBy = u1.Id
LEFT JOIN ossys_User u2 ON c.CreatedBy = u2.ID
LEFT JOIN ossys_User u3 ON c.OwnedBy = u3.Id
INNER JOIN PROVIDER p ON c.TargetId = p.Id
INNER JOIN CONTRACTS con ON p.Contract = con.Contract
WHERE
c.LastUpdatedDt BETWEEN '2019-01-01' AND '2019-07-01'
Order By c.CreatedDt ASC

UPDATE all records from existing SELECT query

I have query to select data from related tables.
SELECT
s.id,
CASE
WHEN count(DISTINCT e.id) <> 0
THEN count(DISTINCT o.id) / count(DISTINCT e.id)
END OrdersAverageNumber
FROM
[School] s
JOIN
[SchoolStore] ss ON ss.SchoolId = s.Id
JOIN
[Event] e ON e.SchoolId = ss.SchoolId
AND e.IsDeleted = 0
AND e.Status = 1
AND e.Date >= #startDate
AND e.Date <= #endDate
JOIN
[Order] o ON o.EventId = e.id
AND o.OrderStatus = 1
AND o.CreatedDate >= #startDate
AND o.CreatedDate <= #endDate
GROUP BY
s.id;
But I can't understand what I need to change to update all OrdersAverageNumber records in School table with values from selection above.
You can use update:
with q as (< your query here >)
update s
set OrdersAverageNumber = q.OrdersAverageNumber
from school s join
q
on s.id = q.id;

How to add IF ELSE by referencing to previous value

I am trying to read my previous value of "OPENSEATING" and store it into the variable #OPENSEATING. For the second query I want it to check first the value of #OPENSEATING if match condition do the below query.
i believe my declaration is correct, is there any syntax error?
DECLARE #OPENSEATING AS BIT
SELECT
'2019-01-31' AS DATE,
(SELECT
THEATRES.OPENSEATING
FROM
SEAT LEFT JOIN THEATRES ON SEAT.ROOMID = THEATRES.ID
LEFT JOIN SHOWTIMES AS B ON THEATRES.ID = B.THEATREID
LEFT JOIN TICKET_ITEMS ON TICKET_ITEMS.SEATNO = SEAT.SEATNO AND B.ID = TICKET_ITEMS.SHOWTIMESID
WHERE
B.ID = A.ID
GROUP BY THEATRES.OPENSEATING) AS #OPENSEATING,
IF(#OPENSEATING =0)
BEGIN
(SELECT
(THEATRES.CAPACITY - COUNT(TICKET_ITEMS.ID)) AS SEATREMAINING
FROM
SEAT LEFT JOIN THEATRES ON SEAT.ROOMID = THEATRES.ID
LEFT JOIN SHOWTIMES ON THEATRES.ID = SHOWTIMES.THEATREID
LEFT JOIN TICKET_ITEMS ON TICKET_ITEMS.SEATNO = SEAT.SEATNO AND SHOWTIMES.ID = TICKET_ITEMS.SHOWTIMESID
WHERE
SHOWTIMES.ID = A.ID
GROUP BY THEATRES.CAPACITY) AS REMAININGSEAT
END
ELSE IF(#OPENSEATING =1)
BEGIN
(SELECT
(THEATRES.CAPACITY - COUNT(TICKET_ITEMS.ID)) AS SEATREMAINING
FROM
SHOWTIMES LEFT JOIN THEATRES ON THEATRES.ID = SHOWTIMES.THEATREID
LEFT JOIN TICKET_ITEMS ON TICKET_ITEMS.SEATNO = SEAT.SEATNO AND SHOWTIMES.ID = TICKET_ITEMS.SHOWTIMESID
WHERE
SHOWTIMES.ID = A.ID
GROUP BY THEATRES.CAPACITY) AS REMAININGSEAT
END
SHOWSCHEDULES.ID AS SHOWSCHEDULE_ID,
A.ID AS SHOWTIME_ID,
A.THEATREID
FROM
SHOWSCHEDULES JOIN SHOWTIMES AS A ON SHOWSCHEDULES.ID = A.SHOWSCHEDULEID
JOIN SHOWLANGUAGES ON A.SHOWLANGUAGEID = SHOWLANGUAGES.ID
WHERE
'2019-01-31' BETWEEN CONVERT(VARCHAR(10), SHOWSCHEDULES.SHOWFROMDATE, 20) AND CONVERT(VARCHAR(10), SHOWSCHEDULES.SHOWTODATE, 20)
AND CONVERT(VARCHAR(8), getdate(), 8) < CONVERT(VARCHAR(10), A.SHOWENDTIME,8)
ORDER BY SHOWBEGINTIME_24 ASC
;
AS SUGGESTED BY #Slava Murygin I tried creating CTE TABLE as below but even this is showing error, what is wrong with my simple cte table. The inner query is working fine.
WITH cte_name (OPENSEATING) AS (
SELECT
(SELECT
THEATRES.OPENSEATING
FROM
SEAT LEFT JOIN THEATRES ON SEAT.ROOMID = THEATRES.ID
LEFT JOIN SHOWTIMES AS B ON THEATRES.ID = B.THEATREID
LEFT JOIN TICKET_ITEMS ON TICKET_ITEMS.SEATNO = SEAT.SEATNO AND B.ID = TICKET_ITEMS.SHOWTIMESID
WHERE
B.ID = A.ID
GROUP BY THEATRES.OPENSEATING) AS OPENSEATING
FROM
SHOWSCHEDULES JOIN SHOWTIMES AS A ON SHOWSCHEDULES.ID = A.SHOWSCHEDULEID
JOIN SHOWLANGUAGES ON A.SHOWLANGUAGEID = SHOWLANGUAGES.ID
WHERE
'2019-01-31' BETWEEN CONVERT(VARCHAR(10), SHOWSCHEDULES.SHOWFROMDATE, 20) AND CONVERT(VARCHAR(10), SHOWSCHEDULES.SHOWTODATE, 20)
AND CONVERT(VARCHAR(8), getdate(), 8) < CONVERT(VARCHAR(10), A.SHOWENDTIME,8)
)
I have made changes to your CTE as:
WITH cte_name (OPENSEATING) AS (
SELECT
THEATRES.OPENSEATING as OPENSEATING
FROM
SEAT LEFT JOIN THEATRES ON SEAT.ROOMID = THEATRES.ID
LEFT JOIN SHOWTIMES AS B ON THEATRES.ID = B.THEATREID
LEFT JOIN TICKET_ITEMS ON TICKET_ITEMS.SEATNO = SEAT.SEATNO AND B.ID = TICKET_ITEMS.SHOWTIMESID
WHERE
B.ID = A.ID
GROUP BY THEATRES.OPENSEATING
)
select openseating from
cte_name, SHOWSCHEDULES JOIN SHOWTIMES AS A ON SHOWSCHEDULES.ID = A.SHOWSCHEDULEID
JOIN SHOWLANGUAGES ON A.SHOWLANGUAGEID = SHOWLANGUAGES.ID
WHERE
'2019-01-31' BETWEEN CONVERT(VARCHAR(10), SHOWSCHEDULES.SHOWFROMDATE, 20) AND CONVERT(VARCHAR(10), SHOWSCHEDULES.SHOWTODATE, 20)
AND CONVERT(VARCHAR(8), getdate(), 8) < CONVERT(VARCHAR(10), A.SHOWENDTIME,8)
You can't do that in one query. You have to get variable in the first query and then use it in IF statement.
If you WANT to use ONLY ONE statement then you have to use CTEs, but it will hide the logic and will be hard to debug.
It might be something like this, but no guarantee it will work, because I have no idea about your business logic and data behind:
;WITH OPENSEATING as (
SELECT THEATRES.OPENSEATING, B.ID
FROM SEAT
LEFT JOIN THEATRES ON SEAT.ROOMID = THEATRES.ID
LEFT JOIN SHOWTIMES AS B ON THEATRES.ID = B.THEATREID
LEFT JOIN TICKET_ITEMS ON TICKET_ITEMS.SEATNO = SEAT.SEATNO AND B.ID = TICKET_ITEMS.SHOWTIMESID
GROUP BY THEATRES.OPENSEATING),
REMAININGSEAT0 as (
SELECT st.ID, (t.CAPACITY - COUNT(ti.ID)) AS SEATREMAINING
FROM SEAT as s
LEFT JOIN THEATRES as t ON s.ROOMID = t.ID
LEFT JOIN SHOWTIMES as st ON t.ID = st.THEATREID
LEFT JOIN TICKET_ITEMS ON ti.SEATNO = s.SEATNO AND st.ID = ti.SHOWTIMESID
GROUP BY t.CAPACITY),
REMAININGSEAT1 as (
SELECT st.ID, (t.CAPACITY - COUNT(ti.ID)) AS SEATREMAINING
FROM SHOWTIMES as st
LEFT JOIN THEATRES as t ON t.ID = st.THEATREID
LEFT JOIN SEAT as s ON s.ROOMID = t.ID
LEFT JOIN TICKET_ITEMS as ti ON ti.SEATNO = s.SEATNO AND st.ID = ti.SHOWTIMESID
GROUP BY t.CAPACITY)
SELECT '2019-01-31' AS DATE
, ss.ID AS SHOWSCHEDULE_ID
, A.ID AS SHOWTIME_ID
, A.THEATREID
, SEATREMAINING = CASE OS.OPENSEATING WHEN 0 THEN RS0.SEATREMAINING ELSE RS1.SEATREMAINING END
FROM SHOWSCHEDULES as ss
INNER JOIN SHOWTIMES AS A ON ss.ID = A.SHOWSCHEDULEID
INNER JOIN SHOWLANGUAGES as SL ON A.SHOWLANGUAGEID = SL.ID
INNER JOIN OPENSEATING as OS ON OS.ID = A.ID
LEFT JOIN REMAININGSEAT0 as RS0 ON RS0.ID = A.ID
LEFT JOIN REMAININGSEAT1 as RS1 ON RS1.ID = A.ID
WHERE '2019-01-31' BETWEEN CONVERT(VARCHAR(10), ss.SHOWFROMDATE, 20) AND CONVERT(VARCHAR(10), ss.SHOWTODATE, 20)
AND CONVERT(VARCHAR(8), getdate(), 8) < CONVERT(VARCHAR(10), A.SHOWENDTIME,8)
ORDER BY SHOWBEGINTIME_24 ASC;

Any Alternatives to Unions in SQL Server?

So, I'm in the process of creating a query that will bring back all the data I need.
Here's my query:
Declare #StartDate datetime
Set #StartDate = '2/1/2018'
Declare #EndDate datetime
Set #EndDate = '4/5/2018'
Declare #UserID int
Set #UserId = '153056'
;with EntData as
(
select
distinct (Entity_ID), a.user_ID, c.User_OrganizationalUnitID
from
ViewMgmt as a
ViewConsole b on a.Role_ID = b.RoleID
ViewUsers c on a.User_ID = c.UserID
where
b.RoleID in ( 53354666, 5363960) and
a.User_ID = #UserID and
a.Entity_ID <> 6912276036227
)
select a.User_ID, a.User_Name, a.UOName,
b.C_OID, c.OName,
d.CID, e.Affected
from view.a
inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
inner join view_New.b on a.CI_D = b.C_ID
left join view_Large.c on b.C_OID = c.OID
left join view_Small.d on a.CI_D = d.CID
left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
inner join EntData on b.C_OID = EntityData.Entity_ID
where ((a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate = a.ExpirationDate)
or (a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate is null)) and (a.UI <> 6912276036227 or a.UI <> 1414)
and a1.IsHidden = 0 and a.UCS <> 13
UNION
select a.User_ID, a.User_Name, a.UOName,
b.C_OID, c.OName,
d.CID, e.Affected
from view.a
inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
inner join view_New.b on a.CI_D = b.C_ID
left join view_Large.c on b.C_OID = c.OID
left join view_Small.d on a.CI_D = d.CID
left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
inner join EntData g on a.UI = g.OID
where ((a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate = a.ExpirationDate)
or (a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate is null)) and a.UI <> 6912276036227
and a.UI = 1414
and (c.OName like '%VXA%' or c.OName like '%Amazon%' or a.CI_D in (414,4561))
and a1.Hidden = 0 and a.UCS <> 13
Originally, the first part of the union was all that I had, but someone wanted to see extra data SPECIFICALLY for one ID (a.UI = 1414). I didn't want to bring back more data for all the UI's in the system, so I made a union to bring back extra data specifically in one UI. The data that I want is coming back; however, now, instead of loading within a minute, the query can take upwards of 4 minutes to load (versus 30-40 seconds for the first SELECT statement). I've been wrestling with this code for a while now and I'm ready to get it working efficiently.
I was trying to think if there was a way to do that last join (inner join EntData g on a.UI = g.OID in the last part of the union, rather than having to tack on a completely separate SELECT statement) only when the UI equals 1414, but I don't think that's possible. I tried implementing that last join into the first SELECT, but it did not run. I'm still a novice with SQL, so any help would greatly be appreciated.
Thank You.
Your joint queries are almost same. Try to join them and make one query from them. I think this query should return same result. But will include duplicate rows if there are.
select a.User_ID, a.User_Name, a.UOName,
b.C_OID, c.OName,
d.CID, e.Affected
from view.a
inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
inner join view_New.b on a.CI_D = b.C_ID
left join view_Large.c on b.C_OID = c.OID
left join view_Small.d on a.CI_D = d.CID
left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
inner join EntData on b.C_OID = EntityData.Entity_ID
where ((a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate = a.ExpirationDate)
or (a.ExpirationDate between #StartDate and #EndDate and a.ExpirationDate is null)) and (a.UI <> 6912276036227)
and a1.IsHidden = 0 and a.UCS <> 13
and 1 = case
when a.UI = 1414
case
when c.OName like '%VXA%' or c.OName like '%Amazon%' or a.CI_D in (414,4561) then 1
else 0
end
else 1
end
I refactored and added some notes.
DECLARE #StartDate datetime
SET #StartDate = '2018-02-01' --- Use ISO 8601 dates. YYYY-MM-DD
DECLARE #EndDate datetime
SET #EndDate = '2018-04-05' --- Use ISO 8601 dates. YYYY-MM-DD
DECLARE #UserID int
SET #UserId = 153056 --- Remove single quotes. You're assigning a string to an int.
; WITH EntData AS (
SELECT DISTINCT Entity_ID , OID /* This needs to be included for later JOIN. Remove the other columns you don't use. */
FROM ViewMgmt a --- USE ANSI-92 syntax. Pretty please.
INNER JOIN ViewConsole b on a.Role_ID = b.RoleID
AND b.RoleID in ( 53354666, 5363960 )
INNER JOIN ViewUsers c on a.User_ID = c.UserID
WHERE
a.User_ID = #UserID
AND a.Entity_ID <> 6912276036227
)
, UnionedQueries AS ( -- Combine the common parts of the UNIONed queries into a second CTE for reuse.
SELECT a.User_ID, a.User_Name, a.UOName
, b.C_OID
, c.OName
, d.CID
, e.Affected
, a.UI -- Added for UNION
, a.CI_D -- Added for UNION
FROM view.a a
INNER JOIN view_Cool.a1 a2 ON a.User_ID = a1.UserID
AND a.CI_D = a1.CID
AND a1.IsHidden = 0 --- Move this filter into the INNER JOIN. It will reduce the JOINed resultset.
INNER JOIN view_New.b b ON a.CI_D = b.C_ID
LEFT JOIN view_Large.c c ON b.C_OID = c.OID
/* These JOINs are connecting across multiple tables. Make sure it's returning what you think it is how it should be. */
LEFT JOIN view_Small.d d ON a.CI_D = d.CID
LEFT JOIN view_Old.e e ON d.Cert_ID = e.CI_D
AND a.User_ID = e.User_ID
WHERE (
( a.ExpirationDate BETWEEN #StartDate AND #EndDate ) /* ??? and a.ExpirationDate = a.ExpirationDate ??? Typo? What was this supposed to do? */
OR
( a.ExpirationDate IS NULL ) --If this is checking for NULL, it won't be BETWEEN #StartDate and #EndDate
--- These two conditions could be combined as ISNULL(a.ExpirationDate,#StartDate), but that is very micro-optimization.
)
and a.UI NOT IN ( 6912276036227, 1414 ) -- This is functionally the same as using two <>s, just easier to follow.
and a.UCS <> 13
)
/* Now that the common query is already run, we can just use those results to get our final UNION */
SELECT u1.User_ID, u1.User_Name, u1.UOName, u1.C_OID, u1.OName, u1.CID, u1.Affected
FROM UnionedQueries u1
INNER JOIN EntData ON u1.C_OID = EntData.Entity_ID -- This JOIN seems to be the only significant difference between the two queries.
UNION
SELECT u2.User_ID, u2.User_Name, u2.UOName, u2.C_OID, u2.OName, u2.CID, u2.Affected
FROM UnionedQueries u2
INNER JOIN EntData g on u2.UI = g.OID -- This JOIN seems to be the only significant difference between the two queries.
WHERE u2.UI = 1414
AND (
u2.OName LIKE '%VXA%'
OR u2.OName LIKE '%Amazon%'
OR u2.CI_D IN ( 414,4561 )
)
;
Note: This will need to be tested. I don't know how much data the EntData CTE filters the queries, so excluding it to the end may result in a much larger dataset in the main queries.