Reputation: 55
I have a problem in SQL Server related to comparing rows in the same table for existence of a value. This table is part of a larger query and is being used within an inner join to fetch matching records. My issue is that the CASE expression I am using in the inner join, particularly the part where I am using a self-join with a NOT EXISTS clause, is making the whole query hang. Basically, it keeps going with producing a result. I think something is wrong especially with that part (the self join and the use of the NOT EXISTS clause). Could anyone help me figure out what I am doing wrong? My main issue is that if there is a row present in Tab2 where the ServiceType is 'ELECTRIC' and the DepID is 'DISCON DEP', it should always pick 'ELECTRIC'. In most cases, both 'ELECTRIC' and 'WATER' are present. The unique case, as seen in LocID 500735, is where only 'WATER' is present. I want it to apply the 'WATER' ServiceType here but only if no 'ELECTRIC' is present for that LocID. I am sure there is something wrong with my query. Is there a way to fix it, or is there a better way to achieve what I want the query to do?
My primary table Tab1 (T1) has the following columns and sample data:
My second table Tab2 (T2) has the following columns and sample data:
I am doing an inner join on the LocID column between Tab1 and Tab2 as:
select T1.LocID, T1.DepID, T2.ServiceType from Tab1 T1
inner join Tab2 T2
ON CASE
WHEN T2.ServiceType='ELECTRIC' AND T1.DepID LIKE '%ELEC%' AND T2.LocID = T1.LocID THEN 1
WHEN T2.ServiceType='ELECTRIC' AND T1.DepID='DISCON DEP' AND T2.LocID = T1.LocID THEN 1
WHEN T2.ServiceType='WATER' AND T1.DepID = 'DISCON DEP' AND T2.LocID = T1.LocID AND NOT EXISTS
(SELECT 1 FROM Tab2 T20
WHERE T2.LocID = T20.LocID
AND T20.ServiceType='ELECTRIC'
AND T20.LocID = T2.LocID) THEN 1
WHEN T2.ServiceType='WATER' AND T1.DepID LIKE '%WATER%' AND T2.LocID = T1.LocID THEN 1
WHEN T2.ServiceType='WATER' AND T1.DepID = 'DISCON DEP WAT' AND T2.LocID = T1.LocID THEN 1
ELSE 0
END = 1
Upvotes: 0
Views: 109
Reputation: 15150
You can simplify that to something like:
SELECT T1.LocID, T1.DepID, T2.ServiceType
FROM Tab1 T1
INNER JOIN Tab2 T2
ON T2.LocID = T1.LocID
AND (
(T2.ServiceType='ELECTRIC' AND T1.DepID LIKE '%ELEC%')
OR (T2.ServiceType='WATER' AND T1.DepID = 'DISCON DEP' AND NOT EXISTS
(SELECT 1 FROM Tab2 T20
WHERE T2.LocID = T20.LocID
AND T20.ServiceType='ELECTRIC'
AND T20.LocID = T2.LocID))
OR (T2.ServiceType='ELECTRIC' AND T1.DepID='DISCON DEP')
OR (T2.ServiceType='WATER' AND T1.DepID LIKE '%WATER%')
OR (T2.ServiceType='WATER' AND T1.DepID = 'DISCON DEP WAT')
)
This will probably not solve your performance issue, to solve that you can try to rewrite your query to a UNION:
SELECT T1.LocID, T1.DepID, T2.ServiceType
FROM Tab1 T1
INNER JOIN Tab2 T2
ON T2.LocID = T1.LocID
AND T2.ServiceType='ELECTRIC'
AND T1.DepID LIKE '%ELEC%'
UNION ALL
SELECT T1.LocID, T1.DepID, T2.ServiceType
FROM Tab1 T1
INNER JOIN Tab2 T2
ON T2.LocID = T1.LocID
AND T2.ServiceType='WATER'
AND T1.DepID = 'DISCON DEP'
AND NOT EXISTS
(SELECT 1 FROM Tab2 T20
WHERE T2.LocID = T20.LocID
AND T20.ServiceType='ELECTRIC'
AND T20.LocID = T2.LocID))
)
UNION ALL
SELECT T1.LocID, T1.DepID, T2.ServiceType
FROM Tab1 T1
INNER JOIN Tab2 T2
ON T2.LocID = T1.LocID
AND T2.ServiceType='ELECTRIC'
AND T1.DepID='DISCON DEP'
UNION ALL
SELECT T1.LocID, T1.DepID, T2.ServiceType
FROM Tab1 T1
INNER JOIN Tab2 T2
ON T2.LocID = T1.LocID
AND T2.ServiceType='WATER'
AND T1.DepID LIKE '%WATER%'
UNION ALL
SELECT T1.LocID, T1.DepID, T2.ServiceType
FROM Tab1 T1
INNER JOIN Tab2 T2
ON T2.LocID = T1.LocID
AND T2.ServiceType='WATER'
AND T1.DepID = 'DISCON DEP WAT'
This is more text, but a lot clearer as to what the query does. Also, this query can use indexes much better (if there are indexes, if not, create them).
Upvotes: 1