如果serial_number
您认为每个产品实际上是唯一的,那么即使是唯一的,您也得到不止一行的原因Serial_Number
是因为您没有正确地为列添加别名。总之,你有:
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
在您的相关子查询中,您对 的第二个引用没有别名serial_number
,这意味着它是指外部表 ( def
) 还是内部表 ( err
) 是不明确的。在名称冲突的情况下,SQL Server 将假定您指的是内部表,因此您基本上有:
WHERE err.serial_number = err.serial_number
这当然会返回所有行,因为一切都等于自己。问题的快速演示:
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;
其输出显示“Test 1”和“Test 2”都作为相关名称返回:
ID Name CorrelatedName
----------------------------------
1 Test 1 Test 1
1 Test 1 Test 2
使用正确的别名,您只会得到一行:
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
所以你的最终查询应该是:
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';
这需要更多的努力,但是当我编写查询时,我将限定所有内容1,这样就可以立即清楚每一列来自哪个表,并且这样的错误变得更容易发现。
1.如果是从一个表中简单选择,我可能不会为别名或限定列引用而烦恼,尽管即使那样我仍然尝试这样做,以防我以后需要添加表