查询应用Where子句BEFORE加入?

时间:2016-02-15 21:23:47

标签: sql postgresql

我真的很困惑,所以我会尽量保持简单。

我们有表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,它仍然会出现同样的错误......

3 个答案:

答案 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相同。如果这些记录以不同的顺序插入,则可能不是这种情况,因此返回的记录与预期不同。