Convert text to float, when text comes in different formats - mysql

I want to store a text as a float. My problem is, that this text comes in different formats , and I cannot influence that. My TEXT column contains strings like
357000
218000.56
500.000.00
I don't have a problem converting the first two strings. I DO have a problem converting the last one, because the decimal mark is the same character as the thousands separator.
How should I deal with this problem? Is there an explicit conversion string-to-float using a format I can define?
EDIT: I forgot to say, that in the above cases, the last . (if there is any) is always the decimal separator if it is followed by a two digits number. So, '153.650' should convert to 153650 for example.

"EDIT: I forgot to say, that in the above cases, the last . (if there is any) is always the >decimal separator if it is followed by a two digits number. So, '153.650' should convert to >153650 for example."
There's your answer.
Check if the character at index (yourString.Length - 3) is one of your delimiters. If it is, then you have a decimal value; if not, you don't. Proceed to strip out all extraneous symbols and then re-insert your choice of decimal separator at the correct index.
Clean? No. But the situation stinks, TBH.

Correct the data before giving them to SQL - a programming language is simpler, for instance using regular expression replace.
s = s.replaceAll("\\D(\\d\\d\\d)", "$1").replaceFirst("\\D". ".");
(Which does not consider signs!)
It first removes non-digits followed by three digits, and then make a period out of the first remaining non-digit. Can be done smarter.
The above is Java, but regex exists in all sensible programming languages.

you can try this
CONVERT(
REPLACE(REPLACE(value, '.', ''), ',', '.'),
DECIMAL(10,2))
this will replace . and, from your string and will convert it into decimal (10,2).
According To Your
SELECT
IF(
LENGTH(
SUBSTRING_INDEX('351.000', '.', - 1)
) >= "3",
CONVERT(
REPLACE("351.000", ".", ''),
DECIMAL (10, 2)
),
CONVERT(
CONCAT(
REPLACE(
LEFT(
'351.000',
LENGTH("351.000") - LOCATE('.', REVERSE("351.000"))
),
'.',
''
),
CONCAT(
".",
SUBSTRING_INDEX('351.000', '.', - 1)
)
),
DECIMAL (10, 2)
)
)
I have tried for
1234.56 gives 1234.56
1234.000.00 gives 1234000.00
and 1234.000 gives 1234000
but it is not a good way to do so much in mysql query. you should handle it in programming part

SQL Fiddle
MySQL 5.5.32 Schema Setup:
CREATE TABLE Table1
(`TEXT` varchar(10))
;
INSERT INTO Table1
(`TEXT`)
VALUES
('357000'),
('218000.56'),
('500.000.00')
;
Query 1:
SELECT CAST(concat(
REPLACE(CASE WHEN substr(TEXT,-3,1) = "." THEN substr(TEXT,1,length(TEXT)-3)
ELSE TEXT END,'.',''),
CASE WHEN substr(TEXT,-3,1) = "." THEN right(TEXT,3)
ELSE '' END) AS decimal(12,2)
) AS Amount
FROM Table1
Results:
| AMOUNT |
|-----------|
| 357000 |
| 218000.56 |
| 500000 |

Related

MySQL format number with unknown number of decimal places

In MySQL, I only want to add thousand separator in the number like 1234.23234, 242343.345345464, 232423.22 and format to "1,234.23234", "242,343.345345464", "232,423.22", use format function need to specify the number of decimals, is there any other function can format the number with unknown number of decimal places? for 1234.23234, I do not want to get the result like 1234.2323400000 or 1234.23, just want to get 1,234.23234.
As suggested split the string drop the trailing zeros format the number before the decimal point and concat taking into account the possibility of no decimals being present at all for example
set #a = 1234.56;
select
case when instr(#a,'.') > 0 then
concat(
format(substring_index(#a,'.',1),'###,###,###'),
'.',
trim(trailing '0' from substring_index(#a,'.',-1))
)
else
format (#a,'###,###,###')
end formatted
MySQL doesn't seem to have such feature. You'll probably need to write a custom function based on FORMAT() plus some string manipulation to remove trailing zeroes after the comma, for example using REGEXP_REPLACE(). The default locale used in FORMAT() is en_US, which seems to be the one you want, so you can omit it or provide your own should you need a different locale.
WITH sample_data (sample_number) AS (
SELECT NULL
UNION ALL SELECT 0
UNION ALL SELECT 0.00001
UNION ALL SELECT 100.01
UNION ALL SELECT 100.0102
UNION ALL SELECT 100.012300456
UNION ALL SELECT 1000
UNION ALL SELECT 123456789.87654321
UNION ALL SELECT -56500.333
)
SELECT
sample_number,
REGEXP_REPLACE(
FORMAT(sample_number, 999),
'(\.\\d*[1-9])(0+$)|(\.0+$)',
'$1'
) AS USA,
-- Replace \. with , for locales that use comma as decimal separator:
REGEXP_REPLACE(
FORMAT(sample_number, 999, 'de_DE'),
'(,\\d*[1-9])(0+$)|(,0+$)',
'$1'
) AS Germany
FROM sample_data;
sample_number
USA
Germany
NULL
NULL
NULL
0.000000000
0
0
0.000010000
0.00001
0,00001
100.010000000
100.01
100,01
100.010200000
100.0102
100,0102
100.012300456
100.012300456
100,012300456
1000.000000000
1,000
1.000
123456789.876543210
123,456,789.87654321
123.456.789,87654321
-56500.333000000
-56,500.333
-56.500,333
Fiddle

MySQL Decimal format

I have 2 TEXT columns in my table (AmountPaid and AmountRemaining). The format is € 10.000,00
I am trying to create a query that pluses these 2 values, and convert it back to the format as show above (€ 10.000,00). Of course this should also work with for example € 100.000.000,00, € 690,00 or € 10,00 etc...
For now I have this query witch plusses the values:
SELECT AmountRemaining, CAST(REPLACE(REPLACE(REPLACE(CAST(AmountRemaining AS CHAR), '€ ', '') , '.', ''), ',00', '') AS DECIMAL) +
CAST(REPLACE(REPLACE(REPLACE(CAST(AmountPaid AS CHAR), '€ ', '') , '.', ''), ',00', '') AS DECIMAL) FROM Clients
The output of this is like this "10000", "13000" etc...
How can I convert this back to the original format?
Thanks.
I have 2 TEXT columns in my table.
Wrong. Text columns contain text. Use numeric columns for numbers. That is, cleanse the data on the way in, not on the way out.
Once you have done that, the rest is better done thus:
Use LOCALE to establish the desired decimal point and thousands separator. That is used in the FORMAT() function to do the rest of the numeric part. T tack on the currency symbol, use CONCAT().
SELECT
CONCAT('€', FORMAT(1234567, 2, 'de_DE'));
+--------------------------------------------+
| CONCAT('€', FORMAT(1234567, 2, 'de_DE')) |
+--------------------------------------------+
| €1.234.567,00 |
+--------------------------------------------+

Custom SQL query, for sorting values with "-" as separators

I am trying to create an ORDER BY to sort my values properly.
The values contain a string and anywhere from zero to three sets of numbers separated by a -.
Example:
dog-2-13
dog-13-54-3
dog-25
cat-63-12
cat
I want them to be sorted firstly by the string in front and then by each of the "number sections" so that: dog-2-14 > dog-2-13 but dog-1-14 < dog-2-13.
Expected result (with more examples to make it clearer):
cat
cat-63-12
dog-2-13
dog-2-14
dog-3
dog-13-53-3
dog-13-54-3
dog-13-54-4
dog-25
I'm a SQL novice and completely lost. Thank you!
Please try...
SELECT fieldName
FROM
(
SELECT fieldName AS fieldName,
SUBSTRING_INDEX( fieldName,
'-',
1 ) AS stringComponent,
CONVERT( SUBSTRING_INDEX( SUBSTRING( fieldName,
CHAR_LENGTH( SUBSTRING_INDEX( fieldName, '-', 1 ) ) + 2 ),
'-',
1 ),
UNSIGNED ) AS firstNumber,
CONVERT( SUBSTRING_INDEX( SUBSTRING( fieldName,
CHAR_LENGTH( SUBSTRING_INDEX( fieldName, '-', 2 ) ) + 2 ),
'-',
1 ),
UNSIGNED ) AS secondNumber,
CONVERT( SUBSTRING( fieldName,
CHAR_LENGTH( SUBSTRING_INDEX( fieldName, '-', 3 ) ) + 2 ),
UNSIGNED ) AS thirdNumber
FROM table1
ORDER BY stringComponent,
firstNumber,
secondNumber,
thirdNumber
) tempTable;
The inner SELECT grabs the field name (which I am assuming is fieldName) and the three components and places each in a separate field and assigning an alias to that field. Each subfield must be included at this point for sorting purposes. The list is then sorted based upon those values.
Once this sorting is performed the outer SELECT chooses the original field from the list in a now sorted order.
The four outer instances of SUBSTRING_INDEX() are used to grab the desired fields from their first argument. As SUBSTRING_INDEX() grabs all of the string from the beginning to just before the first occurence of the delimiting character this makes finding the first field easy (Note : I am assuming that the first field shall contain no hyphens).
The first argument for the remaining occurences of SUBSTRING_INDEX() is formed by using SUBSTRING() to grab everything from just after the parsed part of fieldName and the following delimiting character. It is told where this is by using CHAR_LENGTH() to count the number of characters before the most recent delimiting character then adding 1 for the most recent delimiting character and another 1 to point SUBSTRING() to the character after the most recent delimiting character.
SUBSTRING_INDEX() will return NULL where it encounters an absent numerical field. Please note that NULL has a different sort value from zero.
The numerical fields are converted into unsigned Integers using CONVERT(). Unsigned integers were chosen as the supplied data does not contain any real numbers. If there are real values then you will need to replace UNSIGNED with DECIMAL. I have also assumed that all of the numbers will be positive.
Further reading...
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_substring-index
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_substring
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_char-length
https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
If you have any questions or comments, then please feel free to post a Comment accordingly.
You can use a Query like this:
SELECT *
FROM yourTable
ORDER BY SUBSTRING_INDEX( SUBSTRING_INDEX(cat,'-',2), '-', -1);
sample
mysql> SELECT SUBSTRING_INDEX('dog-13-54-4','-',2);
+--------------------------------------+
| SUBSTRING_INDEX('dog-13-54-4','-',2) |
+--------------------------------------+
| dog-13 |
+--------------------------------------+
1 row in set (0,00 sec)
mysql>
mysql> SELECT SUBSTRING_INDEX( SUBSTRING_INDEX( 'dog-13-54-4','-',2), '-', -1);
+------------------------------------------------------------------+
| SUBSTRING_INDEX( SUBSTRING_INDEX( 'dog-13-54-4','-',2), '-', -1) |
+------------------------------------------------------------------+
| 13 |
+------------------------------------------------------------------+
1 row in set (0,00 sec)
mysql>

MySQL - Return from a string the leftmost characters from 2 different characters

I have a database with some codes seperated by / or -, I want to show the left side only, this is an example of the data:
45/84
12/753
68-53
15742-845
2/556
So, i want to get this:
45
12
68
15742
2
I tried using LEFT(), but this search for 1 character only, and returns a warning if the character is not found, this is what LEFT(field,'/') returns.
45
12
(WARNING)
(WARNING)
2
So, what about a REGEXP?
an IF?
any way to ignore from the first non numeric character?
I dont' have more ideas...
Thank you!
Try this:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(col, '-', 1), '/', 1)
FROM mytable
Demo here
You can do it with this statement. Replace the string '15742/845' with your fieldname
SELECT SUBSTRING_INDEX( REPLACE('15742/845','/','-'), '-', 1)

MySQL Logical Operators in a field with text and integers

I have a table that looks like:
ATTRIBUTE1 | ATTRIBUTE2
weight: 190| height: 175
ctr: 400 | dmd: 19
Is it possible to do comparative operations on these fields?
Like, if I wanted to find everyone with a weight less than 200, what would the syntax look like for that? I figure the query would look like the following, if there were no text in the field:
SELECT * FROM mytable WHERE attribute1 < '200'
But since the field has the defining text "weight:", I'm not quite sure how to do this.
Rather
CAST(SUBSTRING(attribute1, INSTR(attribute, ': ') AS SIGNED)
because the value contains the string in the beginning.
Basically you do like this:
Find the index of ': ' and use it as a substring for the value (to skip everything until the actual number). Then you cast it to an Int
(maybe you need to add a +1 to INSTR. I'm not sure since i don't have a mysql client right here
where cast(substring(ATTRIBUTE1, instr(ATTRIBUTE1, ': ')+1 ) as unsigned) <200
alternative:
where cast(replace(Field_2, 'weight: ', '') as unsigned) > 180