If serial_number
is in fact unique per product as you thought, the reason you are getting more than one row even though Serial_Number
is unique is because you have not aliased your columns properly. In summary you have:
SELECT ( select distinct left(product, 6)
from dbo.QS_WIP_Errors2 err
where err.SERIAL_NUMBER = serial_number) -- NO ALIAS ON serial_number
FROM dbo.QS_defects def
In your correlated subquery you have no alias on the second reference to serial_number
, which means it is ambiguous as to whether it refers to the outer table (def
) or the inner table (err
). In the case of a name collision SQL Server will assume that you mean the inner table, so you essentially have:
WHERE err.serial_number = err.serial_number
Which will of course return all rows because everything equals itself. A quick demonstation of the issue:
DECLARE @T TABLE (ID INT, Name VARCHAR(20));
INSERT @T (ID, Name) VALUES (1, 'Test 1'), (2, 'Test 2');
SELECT *
FROM @T AS T1
OUTER APPLY
( SELECT CorrelatedName = Name
FROM @T AS T2
WHERE T2.ID = ID
) AS T3
WHERE T1.ID = 1;
The output of this shows that both "Test 1" and "Test 2" are returned as the correlated name:
ID Name CorrelatedName
----------------------------------
1 Test 1 Test 1
1 Test 1 Test 2
With the correct alias, you only get a single row:
DECLARE @T TABLE (ID INT, Name VARCHAR(20));
INSERT @T (ID, Name) VALUES (1, 'Test 1'), (2, 'Test 2');
SELECT *
FROM @T AS T1
OUTER APPLY
( SELECT CorrelatedName = Name
FROM @T AS T2
WHERE T2.ID = T1.ID
) AS T3
WHERE T1.ID = 1;
ID Name CorrelatedName
----------------------------------
1 Test 1 Test 1
So your final query should probably be:
SELECT CASE WHEN def.serial_number LIKE '550092%' THEN
( SELECT LEFT(err.Product, 6)
FROM dbo.QS_WIP_Errors2 AS err
WHERE err.serial_number = def.serial_number
)
ELSE LEFT(def.serial_number, 6)
END AS IdentNumber
FROM dbo.QS_defects AS def
WHERE def.inspect_time >= '2015-08-01'
AND def.inspect_time <= '2015-08-10';
It is a little more effort, but when I am writing queries I will qualify everything1, this way it is immediately clear exactly what table each column is from, and errors like this become much easier to spot.
1. If it is a simple select from one table I may not bother with an alias, or qualifying column references, although even then I still try to do it, just in case I need to add tables at a later date