Search code examples
mysqlnegative-numbercomparison-operators

Using 'Greater than' operator with a negative number


I need to run several queries against columns containing both positive and negative numbers and return all rows that are either < or > than a selected value, however it's not returning the expected results when I use a 'Greater than' operator if the selected value is a negative number.

Please note that when the selected value is a negative number it should be returning both positive and negative numbers, and it seems to be excluding the negative numbers from the results.

SELECT T3.*    
FROM Rules T3
WHERE T3.Width > '-.80';

The values contained in T3.Width are:

0.90,(0.70),(0.70),(0.70),(0.70),(1.00),(1.00),(1.00),(1.00),(0.90),(0.55),(0.50)

Therefore the result should be:

0.90,(0.70),(0.70),(0.70),(0.70),(0.55),(0.50)

However the result being returned is:

0.90


Solution

  • The easiest solution is of course to use a DECIMAL() or FLOAT column in the table.

    Since you are working with VARCHAR() types and prefer to continue working with VARCHAR, the RDBMS is not correctly treating () enclosed values as negatives, and instead attempting to cast the strings to an integer (which results in zero, and an incorrect comparison).

    Working around the () enclosed negatives:

    Using the ()-enclosed negative values, you can REPLACE() the opening ( with a - and REPLACE() the closing ) with nothing, resulting in a value like -0.70, but it is still a string to MySQL. You must then CAST it to a decimal value for the < > comparison.

    SELECT Width
    FROM T3
    WHERE
      /* Replace the ( to -, and the ) with nothing
       * then cast it to a decimal value
       */ 
      CAST(REPLACE(REPLACE(Width, '(', '-'), ')', '') AS DECIMAL(10,2)) > '-0.8'
    

    Example in action

    Working with regular negative values in a VARCHAR column

    If you change them to regular negative numbers but retain the VARCHAR type, you don't need all the nested REPLACE() but you will still need to cast it to a DECIMAL(10,2).

    SELECT Width
    FROM T3
    WHERE 
      CAST(Width AS DECIMAL(10,2)) > '-0.8'
    

    Example 2: