SQL: No Sub-Query but only Joins - sql-server

I am trying to find an alternative to this query where no sub-select is present but only joins (left, right, inner etc).
select count(SC.NUMBER_C)
from FNQP2PORTAL.SA.SEC_CAS SC
where SC.NUMBER_C not in (
select E.Reference from
FNQP2HQ.dbo.Entities E
join FNQP2HQ.dbo.Classes C on C.ID = E.ClassID
where C.Reference = 'Assembly case')
So, it should be something like...
select count(SC.NUMBER_C)
from FNQP2PORTAL.SA.SEC_CAS SC
left join FNQP2HQ.dbo.Entities E on E.Reference = SC.NUMBER_C and E.Reference IS NULL
inner join FNQP2HQ.dbo.Classes C on C.ID = E.ClassID and C.Reference = 'Assembly case'
Can somebody help me here?

The queries you posted are very different. One is inclusive (where SC.NUMBER_C IN.... - and the other is exclusive (left outer join where E.Reference is NULL). Because of these completely different queries, it's unclear what you're trying to do.
This is how you would accomplish your first query with a join instead of the subquery.
SELECT COUNT(SC.NUMBER_C)
FROM FNQP2PORTAL.SA.SEC_CAS SC
JOIN FNQP2HQ.dbo.Entities E
ON SC.NUMBER_C = E.Reference
JOIN FNQP2HQ.dbo.Classes C
ON C.ID = E.ClassID
WHERE C.Reference = 'Assembly Case'
EDIT:
You need to use a subquery and NOT IN to get what you're asking for in your comment. You can't only use joins.
SELECT COUNT(SC.NUMBER_C)
FROM FNQP2PORTAL.SA.SEC_CAS SC
WHERE SC.NUMBER_C NOT IN
(
SELECT E.Reference
FROM FNQP2HQ.dbo.Entities E
JOIN FNQP2HQ.dbo.Classes C
ON C.ID = E.ClassID
WHERE C.Reference = 'Assembly Case'
)

select count(SC.NUMBER_C)
from FNQP2PORTAL.SA.SEC_CAS SC
INNER JOIN FNQP2HQ.dbo.Entities E on SC.NUMBER_C = E.Reference
INNER JOIN FNQP2HQ.dbo.Classes C on C.ID = E.ClassID
where C.Reference = 'Assembly case'

One reason people use the WHERE IN logic is because of duplicates being returned via join. So in this case moving the logic to inner joins could result in the count inflating. Here's how you would work around that:
select count(SC.NUMBER_C)
from FNQP2PORTAL.SA.SEC_CAS SC
inner join
(
select distinct E.Reference
from FNQP2HQ.dbo.Entities E
join FNQP2HQ.dbo.Classes C on C.ID = E.ClassID
where C.Reference = 'Assembly case'
) as b
on b.reference = sc.NUMBER_C

Try the below code , it may throw error as you have not share the sample data with us. But you should use exists clause.
SELECT COUNT(SC.NUMBER_C)
FROM FNQP2PORTAL.SA.SEC_CAS SC,
FNQP2HQ.dbo.Classes C,
FNQP2HQ.dbo.Entities E
WHERE C.ID = E.ClassID
AND C.Reference = 'Assembly Case'
and not exists(
select 1 from FNQP2HQ.dbo.Entities E1
ON SC.NUMBER_C = E1.Reference)

Related

SQL to find which table has diag_code filled, and then look it up in lookup_table

I have a query and a diag_code is either in one table (UM_SERVICE) or the other (LOS), but I can't join both tables to get diag_code that isn't null, that I can think of. Does this look ok for finding if diag_code is in one of the tables and lookup table? It's possible to have both LOS and UM_SERVICE have a diag code on different rows, and they could be different, and both or one could be in the lookup table. I'm not seeing anything in internet search.
Here's a simplified stored procedure:
SELECT distinct
c.id
,uc.id
,c.person_id
FROM dbo.CASES c
INNER JOIN dbo.UM_CASE uc with (NOLOCK) ON uc.case_id = c.id
LEFT JOIN dbo.UM_SERVICE sv (NOLOCK) ON sv.case_id = omc.case_id
LEFT JOIN dbo.UM_SERVICE_CERT usc on usc.service_id = sv.id
LEFT JOIN dbo.LOS S WITH (NOLOCK) ON S.case_id = UC.case_id
LEFT JOIN dbo.LOS_EXTENSION SC WITH (NOLOCK) ON SC.los_id = S.id
INNER JOIN dbo.PERSON op with (NOLOCK) on op.id = c.Person_id
WHERE
(sv.diag_code is not null and c.case_id = sv.case_id
or
s.diag_code is not null and c.case_id = s.case_id)
and
(sv.diag_code is not null and sv.diag_code in (select diag_code from TABLE_LOOKUP)
or
s.diag_code is not null and s.diag_code in (select diag_code from TABLE_LOOKUP)
Table setups like this:
CASES
id person_id
UM_CASE
case_id
LOS
case_id id
LOS_EXTENSION
los_id
Person
id cid
UM_SERVICE
case_id diag_code
UM_SERVICE_CERT
service_id id
TABLE_LOOKUP
diag_code
Since you have two different searches being run, it is going to be much easier to write/read by writing the searches individually and then bringing your two results sets together using the UNION operator. The UNION will eliminate duplicates across the two result sets in a similar manner to what your usage of SELECT DISTINCT is doing for a single result set.
Like so:
/*first part of union performs seach using filter on dbo.UM_SERVICE*/
SELECT
c.id
,uc.id
,c.person_id
FROM
dbo.CASES AS c
INNER JOIN dbo.UM_CASE AS uc ON uc.case_id=c.id
LEFT JOIN dbo.UM_SERVICE AS sv ON sv.case_id = omc.case_id
LEFT JOIN dbo.UM_SERVICE_CERT AS usc on usc.service_id=sv.id
LEFT JOIN dbo.LOS AS S ON S.case_id = UC.case_id
LEFT JOIN dbo.LOS_EXTENSION AS SC ON SC.los_id= S.id
INNER JOIN dbo.PERSON AS op on op.id=c.Person_id
WHERE
sv.diag_code in (select diag_code from TABLE_LOOKUP) /*will eliminate null values in sv.diag_code*/
UNION /*deduplicate result sets*/
/*second part of union performs search using filter on dbo.LOS*/
SELECT
c.id
,uc.id
,c.person_id
FROM
dbo.CASES AS c
INNER JOIN dbo.UM_CASE AS uc ON uc.case_id=c.id
LEFT JOIN dbo.UM_SERVICE AS sv ON sv.case_id = omc.case_id
LEFT JOIN dbo.UM_SERVICE_CERT AS usc on usc.service_id=sv.id
LEFT JOIN dbo.LOS AS S ON S.case_id = UC.case_id
LEFT JOIN dbo.LOS_EXTENSION AS SC ON SC.los_id= S.id
INNER JOIN dbo.PERSON AS op on op.id=c.Person_id
WHERE
s.diag_code in (select diag_code from TABLE_LOOKUP); /*will eliminate null values in s.diag_code*/

How to improve SQL Server performance issue with hash match right outer join

I am new to performance issues. So I am not sure of what my approach should be.
This is the query that is taking over 7 minutes to run.
INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID)
SELECT
PV.PatientVisitId AS PatientEncounterID,
InsSub.InsuranceSubscriberID
FROM
DB1.dbo.PatientVisit PV
JOIN
DB1.dbo.PatientVisitInsurance PVI ON PV.PatientVisitId = PVI.PatientVisitId
JOIN
DB1.dbo.PatientInsurance PatIns on PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN
DB1.dbo.PatientProfile PP On PP.PatientProfileId = PatIns.PatientProfileId
LEFT OUTER JOIN
DB1.dbo.Guarantor G ON PatIns.PatientProfileId = G.PatientProfileId
JOIN
Warehouse.dbo.InsuranceSubscriber InsSub ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND ((InsSub.GuarantorID = G.GuarantorId) OR (InsSub.GuarantorID IS NULL AND G.GuarantorId IS NULL))
JOIN
Warehouse.dbo.Encounter E ON E.PatientEncounterID = PV.PatientVisitId
The execution plan states that there is a
Hash Match Right Outer Join that Cost 89%
of the query.
There is not a right outer join in the query so I don't see where the problem is.
How can I make the query more efficient?
Here is the Hash Map Detail:
To elaborate on my comment you could try splitting it into two queries, the first to match on GuarantorID and the second to match when it is NULL in InsuranceSubscriber, and in Guarantor, or if the record is missing completely from Guarantor:
INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID)
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV
JOIN DB1.dbo.PatientVisitInsurance PVI
ON PV.PatientVisitId = PVI.PatientVisitId
JOIN DB1.dbo.PatientInsurance PatIns
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN DB1.dbo.PatientProfile PP
ON PP.PatientProfileId = PatIns.PatientProfileId
JOIN DB1.dbo.Guarantor G
ON PatIns.PatientProfileId = G.PatientProfileId
JOIN Warehouse.dbo.InsuranceSubscriber InsSub
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND InsSub.GuarantorID = G.GuarantorId
JOIN Warehouse.dbo.Encounter E
ON E.PatientEncounterID = PV.PatientVisitId
UNION ALL
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV
JOIN DB1.dbo.PatientVisitInsurance PVI
ON PV.PatientVisitId = PVI.PatientVisitId
JOIN DB1.dbo.PatientInsurance PatIns
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN DB1.dbo.PatientProfile PP
ON PP.PatientProfileId = PatIns.PatientProfileId
JOIN Warehouse.dbo.InsuranceSubscriber InsSub
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND InsSub.GuarantorID IS NULL
JOIN Warehouse.dbo.Encounter E
ON E.PatientEncounterID = PV.PatientVisitId
WHERE NOT EXISTS
( SELECT 1
FROM DB1.dbo.Guarantor G
WHERE PatIns.PatientProfileId = G.PatientProfileId
AND InsSub.GuarantorID IS NOT NULL
);
I would re-order the joins based on the ability to reduce the number of records returned by each join. Whichever join can reduce the number or records returned will increase efficiency. Then perform the outer join. Also, table locking can always be an issue so add with(nolock) to prevent records that are locked.
Perhaps something like this would work with a little tweaking.
INSERT INTO SubscriberToEncounterMapping (
PatientEncounterID
, InsuranceSubscriberID
)
SELECT PV.PatientVisitId AS PatientEncounterID
, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV WITH (NOLOCK)
INNER JOIN Warehouse.dbo.Encounter E WITH (NOLOCK)
ON E.PatientEncounterID = PV.PatientVisitId
INNER JOIN DB1.dbo.PatientVisitInsurance PVI WITH (NOLOCK)
ON PV.PatientVisitId = PVI.PatientVisitId
INNER JOIN DB1.dbo.PatientInsurance PatIns WITH (NOLOCK)
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
INNER JOIN DB1.dbo.PatientProfile PP WITH (NOLOCK)
ON PP.PatientProfileId = PatIns.PatientProfileId
INNER JOIN Warehouse.dbo.InsuranceSubscriber InsSub WITH (NOLOCK)
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
LEFT JOIN DB1.dbo.Guarantor G WITH (NOLOCK)
ON PatIns.PatientProfileId = G.PatientProfileId
AND (
(InsSub.GuarantorID = G.GuarantorId)
OR (
InsSub.GuarantorID IS NULL
AND G.GuarantorId IS NULL
)
)

How to group row value using SQL Server?

I want to group same yAxisTitle in SQL Server, below image shows my data.
Expected result:
Query I used:
select
q.questionId, q.questionName,
p.perspectiveTitle, x.xAxisTitle, y.yAxisTitle, c.value
from
coaching_questionPerspectiveMap as c
inner join
Coaching_question as q on c.questionId = q.questionId
inner join
Coaching_perspective as p on c.perspectiveId = p.perspectiveId
inner join
coaching_xAxisData x on c.xAxisDataId = x.xAxisDataId
inner join
coaching_yAxisData y on c.yAxisDataId = y.yAxisDataId
where
q.questionId = 14
and p.perspectiveId = 1
order by
c.sort
Please provide any solution?
Thanks,
If you just want the data ordered so that it shows in groups of yAxisTitle, use this:
select
q.questionId, q.questionName,
p.perspectiveTitle, x.xAxisTitle, y.yAxisTitle, c.value
from
coaching_questionPerspectiveMap as c
inner join
Coaching_question as q on c.questionId = q.questionId
inner join
Coaching_perspective as p on c.perspectiveId = p.perspectiveId
inner join
coaching_xAxisData x on c.xAxisDataId = x.xAxisDataId
inner join
coaching_yAxisData y on c.yAxisDataId = y.yAxisDataId
where
q.questionId = 14
and p.perspectiveId = 1
order by
y.yAxisTitle, c.sort

TSQL: SUM not working like i thought it would

I have the following query:
SELECT
a.Name,
ISNULL(CAST(sum((b.qty * b.unit_rate)* b.Eng_RPQ )/100 AS DECIMAL(8,1)),0) AS [EngHours],
SUM(BR.BlendedRate)
FROM
Activity_Details b
INNER JOIN
Activity c on b.activity_id = c.id
INNER JOIN
Project p on p.id = c.project_id
RIGHT OUTER JOIN
Discipline a on c.discipline_id = a.id
INNER JOIN
(SELECT
a.Name, c.id,
CAST(f.POH * (d.HourlyRate * (1-(r.Discount/100))/100) AS DECIMAL(8,2)) AS BlendedRate
FROM
Activity_Details b
INNER JOIN
Activity c on b.activity_id = c.id
INNER JOIN
Team f on f.activity_id = c.id
INNER JOIN
SOF_Details d on d.id = f.sof_detail_id
INNER JOIN
Project p on p.id = c.project_id
INNER JOIN
Rate r on r.projectid = p.id
INNER JOIN
Teammate_Type tt on tt.id = f.team_type_id
RIGHT OUTER JOIN
Discipline a on c.discipline_id = a.id
GROUP BY
a.Name, c.id, f.POH, d.HourlyRate, r.Discount) AS BR ON BR.id = c.id
GROUP BY
a.Name
ORDER BY
a.Name
Which yields:
Name EngHours BlendedRate
Architechtural 80.8 38.48
Architechtural 80.8 55.33
Architechtural 80.8 55.40
I want to SUM this BlendedRate and ROUND it but if i try SUM(BR.BlendedRate) to the SELECT and remove the BR.BlendedRate in the GROUP BY
I get:
Name EngHours BlendedRate
Architechtural 242.3 895.26
I was expecting BlendedRate to equal 149.21
Any idea what i am doing wrong?
unable to comment due to reputation. It is a crude solution, but your code is returning duplicated (seemingly 6) records. The code should be fixed elsewhere, but without sample data it is difficult. In the mean time a crude solution would be to add a distinct clause to the sum function
SUM( DISTINCT BR.BlendedRate)

Select only columns from joined tables from CTE

The following is my CTE:
;WITH CTE AS
(SELECT O.*, E.Num, E.Amount
FROM OData O
INNER JOIN Equip E
ON O.Name = E.Name)
SELECT * FROM CTE -- gives results I want to join to
The following is the query that I want to SELECT from (and only use this SELECT statement for my query results:
SELECT
MU.Type
,MU.Num
,MU.MTBUR
,MF.MTBF
,MU.Hours
,MF.Hours
FROM
MUType_Stage MU
INNER JOIN
MFType_Stage MF
ON
MU.Type = MF.Type
AND
MU.Num = MF.Num
-- Need do JOIN to CTE right here
INNER JOIN
Status_STAGE S
ON
MU.Nu = S.Part
LEFT OUTER JOIN
RCN N
ON
N.Name = R.Part
LEFT OUTER JOIN
Repair RR
ON
R.ACSS_Name = RR.Name
So basically I need to JOIN to the CTE inside the SELECT query in which I want the results.
OR ALTERNATIVELY Uses this select statement to join to the CTE but only what the selected columns from the second select statement
Try this syntax
WITH CTE
AS (SELECT O.*,
E.Num,
E.Amount
FROM OData O
INNER JOIN Equip E
ON O.Name = E.Name)
SELECT MU.Type,
MU.Num,
MU.MTBUR,
MF.MTBF,
MU.Hours,
MF.Hours
FROM MUType_Stage MU
INNER JOIN MFByACType_Stage MF
ON MU.Type = MF.Type
AND MU.Num = MF.Num
INNER JOIN CTE C --- JOIN HERE as like other tables
ON C.Num = MF.Num
INNER JOIN Status_STAGE S
ON MU.Nu = S.Part
LEFT OUTER JOIN RCN N
ON N.Name = R.Part
LEFT OUTER JOIN Repair RR
ON R.ACSS_Name = RR.Name

Resources