我正在使用以下查询:
SELECT *
FROM TableA a
WHERE a.FieldA IN (
CASE
--select subquery returns a single value
WHEN a.FieldB = 'Value1'
THEN (select b.ID from TableB b where b.FK_Field = '123')
--select subquery returns multiple values
WHEN a.FieldB = 'Value2'
THEN (select c.ID from TableC c where c.FK_Field = '123')
END
)
第一个case select语句只返回一个b.ID
。如果我有这个陈述,我的代码就可以了。
然而,第二个case语句返回多个c.ID
s。当我添加该检查时,我收到以下错误:
子查询返回的值超过1。这是不允许的 子查询跟随=,!=,<,< =,>,> =或当子查询用作 表达。
如果我有WHERE a.FieldA =
,那么我理解子查询只能返回1个值。但是我有WHERE a.FieldA IN
,那么为什么如果有多个值返回会抱怨?
我该如何实施这种检查?
答案 0 :(得分:1)
正如@marc_s在评论中解释的那样:
T-SQL中的CASE是一个返回单个表达式的表达式(如a + b), 原子值 - 您不能使用它来有选择地运行那些SQL片段 返回整个结果集
为了解决此错误,我删除了CASE
语句,而是使用了一堆AND
和OR
语句来完成相同类型的检查。
SELECT *
FROM TableA a
WHERE
(a.FieldB = 'Value1'
AND a.FieldA IN (select b.ID from TableB b where b.FK_Field = '123'))
OR (a.FieldB = 'Value2'
AND a.FieldA IN (select c.ID from TableC c where c.FK_Field = '123'))
这段代码比CASE
语句有点麻烦,但它有效。
答案 1 :(得分:1)
这样做的方法很多,这里是使用union all和相关EXISTS语句的一种方法
;WITH cte AS (
SELECT 'Value1' as FieldB, b.Id
FROM
TableB
WHERE
b.FK_FieldId = '123'
UNION ALL
SELECT 'Value1' as FieldB, c.Id
FROM
TableB
WHERE
c.FK_FieldId = '123'
)
SELECT *
FROM
TableA a
WHERE
EXISTS (SELECT 1
FROM
cte c
WHERE
a.FieldB = c.FieldB
AND a.FieldA = c.Id)
你编写它的方式的问题是你得到一个非标量值(意思是超过1行),其中sql期望一个标量值。在case表达式中,只有标量值可以在THEN部分中使用,也可以在WHEN中使用一些规则。要解决此问题,您需要将case表达式拆分为多个where语句和/或使用其他一些技术,例如上面的那些。
或者您可以像这样编写案例表达式:
SELECT *
FROM
TableA a
WHERE
(CASE
WHEN a.FieldB = 'Value1' AND a.FieldA IN (select b.ID from TableB b where b.FK_Field = '123') THEN 1
WHEN a.FieldB = 'Value2' AND a.FieldA IN (select c.ID from TableC c where c.FK_Field = '123') THEN 1
ELSE 0
END) = 1
答案 2 :(得分:0)
如果没有必要,请不要在谓词中使用case
- 使用case使你的参数non-SARG
(你不会使用索引)。
SELECT *
FROM TableA a
WHERE EXISTS(
SELECT NULL
FROM TableB b
WHERE a.FieldB = 'Value1'
AND b.FK_Field = '123'
AND a.FieldA = b.ID))
OR EXISTS(
SELECT NULL
FROM TableC c
WHERE a.FieldB = 'Value2'
AND c.FK_Field = '123'
AND a.FieldB = c.ID))
使用索引。并尝试让你的qry可读。
或者,如果您想使用半连接:
SELECT *
FROM TableA a
WHERE a.FieldA IN (
SELECT b.ID
FROM TableB b
WHERE a.FieldB = 'Value1'
AND b.FK_Field = '123'))
OR a.FieldB IN (
SELECT c.ID
FROM TableC c
WHERE a.FieldB = 'Value2'
AND c.FK_Field = '123'))
这两种解决方案均适用于SARG。