CREATE FUNCTION normalize_district (district VARCHAR(4))
RETURNS VARCHAR(4) DETERMINISTIC
RETURN CONCAT( TRIM(TRAILING CASE WHEN 0 + RIGHT(district, 2) > 0
THEN RIGHT(district, 2)
ELSE RIGHT(district, 1) END FROM district),
LPAD(CASE WHEN 0 + RIGHT(district, 2) > 0
THEN 0 + RIGHT(district, 2)
ELSE 0 + RIGHT(district, 1) END, 2, '0') );
and then
SELECT *
FROM district_to_test
LEFT JOIN rate ON normalize_district(district_to_test.district)
BETWEEN normalize_district(district_from)
AND normalize_district(district_to);
fiddle
0 + RIGHT(district, 2) > 0
in the function thecks does the last 2 symbols in district
are digits.
If true then 2-digit number wil be extracted by RIGHT(), and the whole expression value will be above zero (you claim that there is no values like 'AA0'
or 'AA00'
).
If false, and only one digit is present, then RIGHT() will give a substring which is started from a letter, and the value will be zero.
Based on this I divide the whole value to a prefix and numeric postfix, and add a zero to the numeric part making it 2-digit unconditionally. Such value can be used for direct string comparing by BETWEEN operator.
The goal of a function is to convert the value to 'AA00'
format. For this purposes we must divide the whole value to textual and numeric parts and normalize (zero-pad) the latter one.
You may use any other dividing method. For example, you may check does the value contains two digits using LIKE '%\\d\\d'
. Or backward, you may determine does the value contains two letters using LIKE '\\D\\D%'
... these methods have relatively equal difficulty.