我真的很困惑,所以我会尽量保持简单。
我们有表A: ID
表B: id ||编号
表A是"预过滤器"因为B包含很多不同的对象,包括A。
所以我的查询,尝试用过滤器获取所有A;
SELECT * FROM A a
JOIN B b ON b.id = a.id
WHERE CAST(SUBSTRING(b.number, 2, 30) AS integer) between 151843 and 151865
由于A的所有实例都以字母开头(" X ******"),我只想截断第一个字母,让过滤器使用指定的数字进行工作。用户。
乍一看,绝对不用担心。但似乎我错了。对于我没想到的事情......似乎我的WHERE子句在我的JOIN之前执行。因此,由于许多B在开始时的号码都超过一个字母,因此我发生了无效的转换。尽管如果我们留在A,它永远不会发生。
我一直认为where子句在连接后执行,但在这种情况下,似乎postgres想要证明我错了。
有任何解释吗?
SQLFiddle演示问题:http://sqlfiddle.com/#!15/cd7e6e/7
即使使用SubQuery,它仍然会出现同样的错误......
答案 0 :(得分:2)
SQL是一种声明性语言。对于select语句,您声明要查找的数据必须满足的条件。您无法选择执行路径,您的查询不会在程序上执行。
因此,优化器可以自由选择它喜欢的任何执行计划,只要它返回您的条件指定的记录。
我建议您将查询更改为强制转换为字符串而不是整数。类似的东西:
WHERE SUBSTRING(b.number, 2, 30) between CAST(151843 AS varchar) and CAST(151865 AS varchar)
答案 1 :(得分:2)
您可以使用正则表达式substr函数删除除数字之外的所有内容:CAST(substring(B.number from '\d') AS integer)
。
请参阅此处的工作示例:http://sqlfiddle.com/#!15/cd7e6e/18
答案 2 :(得分:0)
B中的A记录在表B中与在A中的ID相同。如果这些记录以不同的顺序插入,则可能不是这种情况,因此返回的记录与预期不同。