This topic came up for me as the result of investigating an error in Redshift. We have a table containing a column of numbers represented as text, but for rows where no value is present a single space is inserted.
Using this table if I do this:
SELECT text_num::INTEGER AS digit_num
FROM relevant_table
WHERE TRIM(text_num) != ''
Then the query executes without issue. However, if I use this as a subquery with an outer where clause:
SELECT * FROM (
SELECT text_num::INTEGER AS digit_num
FROM relevant_table
WHERE TRIM(text_num) != '') AS subquery
WHERE digit_num BETWEEN 2 AND 5;
It produces an error associated with attempting to cast a space to an integer value.
Looking into the explain plan the source of the error feels obvious. The optimizer has constructed a filter operating off of "relevant_table" which is attempting to directly filter the column like this
text_num::INTEGER >= 3 AND text_num::INTEGER <= 5 AND TRIM(text_num) != ''
My gut says this is not correct. SQL operates, usually, in a sort of set based manner, and the actions of the optimizer aren't forcing any order of operations on the application of the filters. I would think that the use of a subquery should make it explicit that the conditions inside that subquery have to be satisfied first even in the case where the optimizer is flattening out the query.
But I don't see an objective standard for this. Is it an error in the optimizer or is this just expected functionality or simply a quirk of the optimizer to be worked around?
INTEGER
, thus creating your error. It's the conversion to digit_num that would not work.