TSQL:SELECT CASE WHEN THEN 子查询:错误:子查询返回超过 1 个值
Posted
技术标签:
【中文标题】TSQL:SELECT CASE WHEN THEN 子查询:错误:子查询返回超过 1 个值【英文标题】:TSQL: SELECT CASE WHEN THEN Subquery: Error: Subquery returns more than 1 Value 【发布时间】:2015-08-28 08:54:25 【问题描述】:我遇到了错误
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
在下面的查询中
select case
when serial_number like ('550092%') then
(select distinct left(product, 6) from dbo.QS_WIP_Errors2 err
where err.SERIAL_NUMBER = serial_number)
--err.SERIAL_NUMBER in (SERIAL_NUMBER))
else left(SERIAL_NUMBER,6)
end as Identnummer
from dbo.QS_defects def
where INSPECT_TIME >= '2015-08-01' and INSPECT_TIME <= '2015-08-10'
(我也试过评论里的代码) 我真的无法解释它,因为我认为通过选择一个不超过一行的不同值可以返回。 我做错了什么??
【问题讨论】:
错误说明了一切——您试图从case when
的then
中投射多个值——您可以使用TOP 1
限制选择,但您应该调查您的数据至于为什么不符合你的预期。
非常感谢 - Top 1 是一个很好的解决方法,我没有想过。据我了解这些表格不可能将相同的 SERIAL_NUMBER 分配给多个产品。无论如何我都会将其标记为已解决,因为问题不在上面的代码中
不要在没有ORDER BY
的情况下使用TOP 1
【参考方案1】:
如果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';
这需要更多的努力,但是当我编写查询时,我会限定 everything1,这样就可以立即清楚每一列来自哪个表,这样的错误就更容易被发现了。
1.如果它是从一个表中简单选择,我可能不会为别名或限定列引用而烦恼,尽管即使那样我仍然尝试这样做,以防我以后需要添加表子>
【讨论】:
以上是关于TSQL:SELECT CASE WHEN THEN 子查询:错误:子查询返回超过 1 个值的主要内容,如果未能解决你的问题,请参考以下文章
CASE WHEN 及 SELECT CASE WHEN的用法
ORACLE CASE WHEN 及 SELECT CASE WHEN的用法