I have strings like... "3/4" and "5/9" and some like... "1/2 km" and "3/4 degree" stored in mysql columns.
I would like to convert them into numbers.
In first case, 3/4 ==> .75.
In more complicated second case, strip off units like "km" and "degree" so
"1/2 km" ==> 0.5.
I think this isn't something you should do in a query, but rather calculate it when it is stored and save the calculated value in the table next to its text value.
But if you want to, you can use some string functions to slice up the value and the do the math yourself:
select
x.Multiplier / x.Divider as Result
from
(select
cast( substr( t.String,
1,
locate('/', t.String) - 1)
as decimal)
as Multiplier,
cast( substr( t.String,
locate('/', t.String) + 1,
locate( ' ',
concat(t.String, ' ')))
as decimal)
as Divider
from
YourTable t) x
Note however, that this may cause trouble if the data is 'invalid'. If it says '0/0 km', it may fail, if it contains 'no data here' it may fail as well.
The above didn't quite work for me so came up with this which does. The query works for '10', '3/4' and '10 3/4'. Obviously you should replace the constructed rows at the bottom with your string or a selected value from a table:
SELECT
IF (
LOCATE(' ',fraction) > 0 OR LOCATE('/',fraction) = 0,
SUBSTRING_INDEX(SUBSTRING_INDEX(fraction,'/','1'),' ','1')
,0
) AS `integer`,
IF (
LOCATE('/',fraction) > 0,
SUBSTRING_INDEX(SUBSTRING_INDEX(fraction,'/','1'),' ','-1'),
0
) AS numerator,
SUBSTRING_INDEX(fraction,'/','-1') AS denominator,
(SELECT `integer`) + ((SELECT numerator) / (SELECT denominator)) AS `decimal`
FROM (
SELECT '10 3/4' AS fraction
UNION SELECT '10'
UNION SELECT '3/4'
) t;
With PHP you could do:
// assuming $vals has the values from the database
$converted = array();
foreach ($vals as $key => $val) {
preg_match("/^(\\d+)\\/(\\d+)/", $val, $matches)
if (count($matches) > 2) {
$numerator = (int) $matches[1];
$denominator = (int) $matches[2];
$converted[$key] = (float) $numerator / $denominator;
}
}
Related
How to update to the same table? i tried to do fraction conversion and update 1 of the rows in the same table but the error "Subquery returns more than 1 row"
Below are the code, (State1 is the table itself, Share field consists of those fraction data like 1/2,1/5 ..)
UPDATE State1 set shareresult =(SELECT
x.Multiplier / x.Divider as Result
from
(select
cast( substr( t.share,
1,
locate('/', t.share) - 1)
as decimal)
as Multiplier,
cast( substr( t.Share,
locate('/', t.Share) + 1,
locate( ' ',
concat(t.Share, ' ')))
as decimal)
as Divider
from
State1 t ) x)
thanks
Finally, i managed to solve my problem with the code below
CREATE TEMPORARY TABLE activity_product_ids AS SELECT x.NumberID, x.Multiplier / x.Divider as Result from (select cast( substr( t.share, 1, locate('/', t.share) - 1) as decimal) as Multiplier, cast( substr( t.Share, locate('/', t.Share) + 1, locate( ' ', concat(t.Share, ' '))) as decimal) as Divider, t.ID as numberID from State1 t) x;
UPDATE State1 a
JOIN activity_product_ids b
ON a.ID=b.NumberID
SET a.shareresult=b.Result;
Thanks for all the replies.
Neither your update statement nor the sub-query has a WHERE clause so it looks like you are trying to update every row with fraction to decimal conversion of every row.
This is a much simpler approach -
UPDATE State1
SET shareresult = ROUND(SUBSTRING_INDEX(share, '/', 1) / SUBSTRING_INDEX(share, '/', -1), 2)
WHERE id = 1;
I suspect this may have already been asked, but I'm not sure how to phrase the question so that SO search engine picks it up.
I have a column called TCID, which contains values in this format:
1.A.1.1.1
4.A.1.1.1
2.B.1.1.10
2.B.1.1.2
...
There are 5 units in this TCID, separated by periods. I want the position to the left to take the highest priority, and then finally the last digit is the lowest priority.
So it would sort like this:
1.A.1.1.1
2.B.1.1.2
2.B.1.1.10
4.A.1.1.1
Here is the query I have so far. It almost works, but the last position is not getting sorted.
SELECT *
FROM system
WHERE cluster = \"$tc_name\"
ORDER BY CAST(SUBSTR( SUBSTRING_INDEX(tcid,'.',1) , 1 ) AS UNSIGNED),
SUBSTR( SUBSTRING_INDEX(tcid,'.',2) , LENGTH( SUBSTRING_INDEX(tcid,'.',1)) + 2 ),
CAST(SUBSTR( SUBSTRING_INDEX(tcid,'.',3) , LENGTH( SUBSTRING_INDEX(tcid,'.',2)) + 2 ) AS UNSIGNED),
CAST(SUBSTR( SUBSTRING_INDEX(tcid,'.',4) , LENGTH( SUBSTRING_INDEX(tcid,'.',3)) + 2 ) AS UNSIGNED)
Can anyone help me fix this or suggest a better way to do this?
There are obviously better ways to store this information in the database, such as storing the values in separate fields. However, it's not always possible to change the code base to do such things.
But I believe you just need to add the final order by to your query in order to for it to work as expected;
SELECT *
FROM system
WHERE cluster = "<some search term>"
ORDER BY CAST(SUBSTR( SUBSTRING_INDEX(tcid,'.',1) , 1 ) AS UNSIGNED),
SUBSTR( SUBSTRING_INDEX(tcid,'.',2) , LENGTH( SUBSTRING_INDEX(tcid,'.',1)) + 2 ),
CAST(SUBSTR( SUBSTRING_INDEX(tcid,'.',3) , LENGTH( SUBSTRING_INDEX(tcid,'.',2)) + 2 ) AS UNSIGNED),
CAST(SUBSTR( SUBSTRING_INDEX(tcid,'.',4) , LENGTH( SUBSTRING_INDEX(tcid,'.',3)) + 2 ) AS UNSIGNED),
CAST(SUBSTR( SUBSTRING_INDEX(tcid,'.',5) , LENGTH( SUBSTRING_INDEX(tcid,'.',4)) + 2 ) AS UNSIGNED);
Please see this sqlfiddle to check
Just for fun...
SELECT *
FROM
(
SELECT '1.A.1.1.1' x
UNION ALL
SELECT '4.A.1.1.1'
UNION ALL
SELECT '2.B.1.1.10'
UNION ALL
SELECT '2.B.1.1.2'
) a
ORDER BY
INET_ATON(CONCAT(MID(x,1,1),MID(x,4,1000)));
I have store weight in lbs in my column which I need to convert to KG. I was able to do it with a simple query:
SELECT ( weight * 0.45 ) as weight from TABLE
However, this doesn't work values which are stored as a range, ex. '200 - 300'. If I use the same query it returns 440.925 instead of 440-661. I understand this is happening because I'm multiplying string but is there a way I can multiple a range value (200-300) to get the desired result.
If not, how should I convert this range ideally?
SUBSTRING_INDEX is useful here:
SELECT IF(
INSTR(weight, '-') > 0, /* Does weight contain a dash? */
CONCAT( /* Yes? Multiply each, and return them: */
SUBSTRING_INDEX(weight, '-', 1) * 0.45,
' - ',
SUBSTRING_INDEX(weight, '-', -1) * 0.45
),
weight * 0.45 /* No? Just simply multiply the weight */
) AS `range`
FROM test
First, we check to see if weight contains a dash, and if it does, split it up, and multiply them out individually.
See an example here: https://www.db-fiddle.com/f/iELvWDjpVGBZEkpdR4jtsK/0
If i understand your question correctly you need to do something like below.
SELECT
CONCAT (
SUBSTRING_INDEX(SUBSTRING_INDEX(column, ' - ', 1), ' - ', -1) * 0.45
, ' - '
, SUBSTRING_INDEX(SUBSTRING_INDEX(column, ' - ', 2), ' - ', -1) * 0.45
)
FROM
table
1) Nesting SUBSTRING_INDEX functions makes it possible to extract items from a string.
2) CAST function is not needed because of MySQL autotype cast.
Using CAST, and SUBSTRING_INDEX functions.
CAST will ensure that even if there are more spaces on either side of the '-' (hyphen) character, it will still convert it into a valid number. You can change the DECIMAL(10,4) to any precision, as per your application requirements.
SUBSTRING_INDEX will find the substring before the occurence of '-' (hyphen) character.
Try this:
SELECT
CONCAT(CAST(SUBSTRING_INDEX(weight, '-', 1) AS DECIMAL(10,4)) * 0.45,
'-',
CAST(SUBSTRING_INDEX(weight, '-', -1) AS DECIMAL(10,4)) * 0.45)
AS weight
FROM table
Please take a look at a table below:
I need "the last part" of "what I have" to be number if it's all number and string if it contains character.
In Excel I've achieved this with the following function (as shown above):
=IFERROR(VALUE(TEXT(D2;"0"));TEXT(D2;"0"))
However I want to do this in mySQL in order to compute more effectively.
I've "floated" somwhere around CASE with CAST or CONVERT and also TRIM functions, but I haven't been able to put up something sensical.
A nice "bonus" would be to extract "the part part" by looking for the last "" character (so first "" from right of the string) but no idea at all how to achieve that.
Use SUBSTRING_INDEX.
Query
SELECT
CASE
WHEN SUBSTRING_INDEX(records.data, '_', -1) > 1 # is int check '00004949' returns 1
THEN SUBSTRING_INDEX(records.data, '_', -1) + 0 # converts '00004949' to 4949
ELSE SUBSTRING_INDEX(records.data, '_', -1)
END
AS word
FROM (
SELECT "TRA_PL_NWL_EMA_NWLY_DAI_000_20170610_IN1_01P002bc" AS DATA
UNION
SELECT "TRA_PL_NWL_EMA_NWLY_DAI_000_2017_0909_JET_00004949" AS DATA
) records
Result
word
----------
01P002bc
4949
Following query will somewhat achieve the task:
SELECT
case
when SUBSTRING_INDEX(value, "_", -1) REGEXP('(^[0-9]+$)')
then Trim(Leading 0 from SUBSTRING_INDEX(value, "_", -1))
else SUBSTRING_INDEX(value, "_", -1)
end as Value
From yourtable;
Click here for Demo
Hope it helps!
I hope this is what u want.
At least it does what you have asked for.
SELECT
CASE
WHEN (
CONVERT(
substring(
txt,
LENGTH(txt) - LOCATE('_', REVERSE(txt))+2,
length(txt)
)
, signed integer
)
) = 0
THEN substring(
txt,
LENGTH(txt) - LOCATE('_', REVERSE(txt))+2,
length(txt)
)
ELSE CONVERT(
substring(
txt,
LENGTH(txt) - LOCATE('_', REVERSE(txt))+2,
length(txt)
)
, signed integer
)
END as NUMBER
from test.test
This is my test Table and result of SQL:
txt NUMBER
DA_DA_ADAD_ADAD_ADAD_asd123 asd123
DA_DA_ADAD_ADAD_ADAD_000123 123
DA_DA_ADAD_ADAD_ADAD_444 444
DA_DA_ADAD_ADAD_ADAD_bsd123 bsd123
DA_DA_ADAD_ADAD_ADAD_csd123 csd123
DA_DA_ADAD_ADAD_ADAD_dsd123 dsd123
Is it possible to sum the digits in a string and sort by that?
Example values: 19, 21
19 Should be transformed to 10. Explanation: 1+9=10
21 Should be transformed to 3. Explanation: 2+1= 3
After calculating these results, the table needs to be sorted by the resulting values (using SORT BY).
Originally, I have those values stored as JSON array, so it's ["1","9"] and ["2","1"], and in order to parse the JSON I'm using replace as follows:
REPLACE(REPLACE(REPLACE(item_qty, '["', ''), '"]', ''), '","', '')
How about trying something like:
SELECT (
SUBSTRING('["1","9"]', 3, 3) +
SUBSTRING('["1","9"]', 7, 7)
) AS sumOfDigits;
And then if the value ["1","9"] is stored in a column named json and the table is named table you van do:
SELECT * FROM (
SELECT table.*, (
SUBSTRING('json', 3, 3) +
SUBSTRING('json', 7, 7)
) AS sumOfDigits
FROM table
) tmp
ORDER BY sumOfDigits;
I would define a function to do the sum, as follow:
DELIMITER //
CREATE FUNCTION add_digits
(
number INTEGER
) RETURNS INTEGER
BEGIN
DECLARE my_sum INTEGER;
SET my_sum = 0;
SET number = ABS(number);
WHILE (number > 0) DO
SET my_sum = my_sum + (number MOD 10);
SET number = number DIV 10;
END WHILE;
RETURN my_sum;
END //
DELIMITER ;
You could also create a function that works directly on your json sting, parsing it for digits and adding their values.