0

I have table invoices and there is column 'total' varchar(255). There are values like these: "500.00", "5'199.00", "129.60", "1.00" and others. I need select records and filter by total column. For example, find records where total is not more than 180.

I tried this:

SELECT total from invoices WHERE invoices.total <= '180'

But in result there are :

125.25
100.50
1593.55 - not correct
4'799.00 - not correct
1.00
-99.00
2406.52 -not correct

How can I fix it and write correct filter for this column? Thanks!

2
  • What is "5'199.00"? Commented Dec 4, 2018 at 12:23
  • you have to convert total to number if not you make a string compare Commented Dec 4, 2018 at 12:23

3 Answers 3

1

You can use cast() function to convert it in float

SELECT total from invoices WHERE cast(invoices.total as decimal(16,2)) <= 180
Sign up to request clarification or add additional context in comments.

1 Comment

Cast will convert 4'799.00 to 4.
0

Why are you storing numbers as strings? That is a fundamental problem with your data model, and you should fix it.

Sometimes, we are stuck with other people's really, really, really bad decisions. If that is the case, you can attempt to solve this with explicit conversion:

SELECT i.total 
FROM invoices i
WHERE CAST(REPLACE(i.total, '''', '') as DECIMAL(20, 4)) <= 180;

Note that this will return an error if you have other unexpected characters in your totals.

4 Comments

Thanks. String because there must be saved format for total as 1'500.00 and others, cant save it as float.
@ForstackForstack storing decimals in string is just very very very plain wrong when you calculate on these strings the results can and will not be precise not something you want to have in a invoice system
@ForstackForstack you must learn to format the results on the front end.
@ForstackForstack totally agree with comments above. You have to save prices in number format in DB. If you need a specific format for showing prices or if you receive them in specific format - you can just transform them.
0

If the string starts with a number, then contains non-numeric characters, you can use the CAST() function or convert it to a numeric implicitly by adding a 0:

SELECT CAST('1234abc' AS UNSIGNED); -- 1234
SELECT '1234abc'+0; -- 1234

To extract numbers out of an arbitrary string you could add a custom function like this:

DELIMITER $$

CREATE FUNCTION `ExtractNumber`(in_string VARCHAR(50)) 
RETURNS INT
NO SQL
BEGIN
    DECLARE ctrNumber VARCHAR(50);
    DECLARE finNumber VARCHAR(50) DEFAULT '';
    DECLARE sChar VARCHAR(1);
    DECLARE inti INTEGER DEFAULT 1;

    IF LENGTH(in_string) > 0 THEN
        WHILE(inti <= LENGTH(in_string)) DO
            SET sChar = SUBSTRING(in_string, inti, 1);
            SET ctrNumber = FIND_IN_SET(sChar, '0,1,2,3,4,5,6,7,8,9'); 
            IF ctrNumber > 0 THEN
                SET finNumber = CONCAT(finNumber, sChar);
            END IF;
            SET inti = inti + 1;
        END WHILE;
        RETURN CAST(finNumber AS UNSIGNED);
    ELSE
        RETURN 0;
    END IF;    
END$$

DELIMITER ;

Once the function is defined, you can use it in your query:

SELECT total from invoices WHERE ExtractNumber(invoices.total) <= 180

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.