为什么需要在此子选择中对子句进行硬编码?

时间:2019-05-15 15:51:30

标签: sql select subquery

我很难理解为什么这个嵌套的SELECT会产生我认为我已明确排除的结果。我怎么了?

这是银行帐户的上下文。

1)首先,我想找到在两个帐号字段中都带有尾随空白的那些帐户-这很简单。请注意clientcode='FOO',因为accounts表中包含来自多个银行的帐户,而我只想查看FOO帐户:

SELECT * FROM Accounts 
WHERE ClientCode = 'FOO'
AND (  AccountId LIKE '% ' OR AccountIdentNo LIKE '% ' )

这很好::我看到的结果为零,因为唯一带有尾随空白的帐户位于另一家银行BAR中。如果我设置clientcode='BAR',那么我会看到那些帐户。

2)其次,我想知道是否存在具有相同ID但没有尾随空格的任何帐户。 1)的结果以后需要合并到其中。
如果只有一个ID列,但是只有两个ID列,那将很简单,因此我必须进行两个子选择。
另外,请注意,我使用a2.ClientCode = a1.ClientCode,所以我的语句中没有多余的硬编码值:

SELECT * FROM Accounts a1
WHERE a1.ClientCode = 'FOO'
AND TRIM( AccountId ) IN
( SELECT AccountId FROM Accounts a2
  WHERE a2.ClientCode = a1.ClientCode
  AND (  a2.AccountId like '% ' OR a2.AccountIdentNo like '% ' )
) 
OR TRIM( AccountIdentNo ) IN
( SELECT AccountIdentNo FROM Accounts a3
  WHERE a3.ClientCode = a1.ClientCode
  AND (  a3.AccountId like '% ' OR a3.ACCOUNTIDENTNO like '% ' )
);

失败,因为我现在从BAR获得结果了?让我们尝试硬编码:

3)第三,在所有三个选择中,我将a2.ClientCode = a1.ClientCode替换为实际的硬编码值:

SELECT * FROM Accounts a1
WHERE a1.ClientCode = 'FOO'
AND TRIM( AccountId ) IN
( SELECT AccountId FROM Accounts a2
  WHERE a2.ClientCode = 'FOO'
  AND (  a2.AccountId like '% ' OR a2.AccountIdentNo like '% ' )
) 
OR TRIM( AccountIdentNo ) IN
( SELECT AccountIdentNo FROM Accounts a3
  WHERE a3.ClientCode = 'FOO'
  AND (  a3.AccountId like '% ' OR a3.AccountIdentNo like '% ' )
);

这行得通!!我得到FOO的零结果,而如果我使用BAR则得到结果。

问题:
为什么世界上2)无效,但3)无效?为什么此软分配不起作用而硬值分配起作用?


表帐户:

ClientCode | AccountId | AccountIdentNo
---------------------------------------
'FOO'      | '111'     | '111'
'BAR'      | '222 '    | '222'
'BAR'      | '333'     | '333 '
'BAR'      | '444'     | '444'

1 个答案:

答案 0 :(得分:1)

您错过了第二个括号。

  0 1 2 3
0 2 2 2 2
1 2 2 2 2
2 3 1 1 1
3 3 1 1 1
4 3 1 1 1
5 3 1 1 1
0 9 9 9 9
1 9 9 9 9
2 9 9 9 9
3 9 9 9 9
4 9 9 9 9

SELECT * FROM Accounts a1 WHERE a1.ClientCode = 'FOO' AND TRIM( AccountId ) IN (( SELECT AccountId FROM Accounts a2 WHERE a2.ClientCode = a1.ClientCode AND ( a2.AccountId like '% ' OR a2.AccountIdentNo like '% ' ) ) OR TRIM( AccountIdentNo ) IN ( SELECT AccountIdentNo FROM Accounts a3 WHERE a3.ClientCode = a1.ClientCode AND ( a3.AccountId like '% ' OR a3.ACCOUNTIDENTNO like '% ' ) )); 的优先级低于OR。没有括号,您的AND变为

WHERE