Converting Degrees/Minutes/Seconds to Decimals using MySQL - mysql

I'm using MySQL version: 5.7.22
I've got two columns Latitude and Longitude both in Degrees/Minutes/Seconds format that I want to convert to Decimal format ex: 48° 52.250' N to 48.93611111
I have the following script but I'm stuck at how to split the degrees minutes and seconds. I cannot hard-code the values as I've done here left(Latitude,2) since the degrees might have 3 decimals as well
SELECT Latitude,
left(Latitude, 2) +
(TRUNCATE((Latitude - TRUNCATE(Latitude)) * 100) / 60) +
(((Latitude * 100) - TRUNCATE(Latitude * 100)) * 100) / (60 * 60) AS DECIMAL_DEGREES
FROM small_ocean_data
The formula for the conversion is this: D + M/60 + S/3600 * -1 if direction in ['W', 'S'] else 1
Any help would be grateful!

Well if I use this formula of yours: D + M/60 + S/3600
Where I believe D is Degrees and M are Minutes and S are Seconds.
With this select:
select SUBSTRING_INDEX('48° 52.250', '°',1) +
(SUBSTRING_INDEX('48° 52.250',' ',1)/60) +
(SUBSTRING_INDEX('48° 52.250','.',1)/3600);
Or for your database:
select SUBSTRING_INDEX(Latitude, '°', 1) +
(SUBSTRING_INDEX(Latitude ,' ',1)/60) +
(SUBSTRING_INDEX(Latitude ,'.',1)/3600) "DECIMAL_DEGREES"
FROM small_ocean_data;
I get 48.81333333333333
48 + 0.8 + 0.013333333333333334
Here is the DEMO

Related

MySQL convert height format to centimeters

I want to convert feet and inches to centimeters format
Format in my DB is:
4'6" (4 feet, 6 inches)
Formula for converting into centimeters
4*30.48 = 121.92 (convert feet to centimeters = multiply by 30.48)
6*2.54 = 15.24 (convert inches to centimeters = multiply by 2.54)
So Result = 121.92 + 15.24 = 137.16 cm
eg:
Actual Table: inches
SELECT * FROM inches
id height
1 4'6"
2 4'7"
3 5'8"
4 5'9"
I expect the following result as centimeters when I do SQL query
id height
1 137.16
2 139.7
3 172.72
4 175.26
Thanks in advance :)
Probably far easier to do on the application level, but if you really had to, you could do it in SQL like this, using the SUBSTR and INSTR functions, and some basic math:
SET #height = '4''6"';
SELECT
SUBSTR(#height, 1, INSTR(#height, '''') - 1) * 12 * 2.54 +
SUBSTR(#height, INSTR(#height, '''') + 1, INSTR(#height, '"') - INSTR(#height, '''') - 1) * 2.54;
-- yields 137.16
Or, applied to your table structure:
SELECT id,
SUBSTR(height, 1, INSTR(height, '''') - 1) * 12 * 2.54 +
SUBSTR(height, INSTR(height, '''') + 1, INSTR(height, '"') - INSTR(height, '''') - 1) * 2.54 AS height
FROM inches;
Application side process will be better,
However,
SELECT
(CAST(SUBSTR(height,1, LOCATE("'",height)-1) AS UNSIGNED) * 30.48) +
(CAST(SUBSTR(height, LOCATE("'",height)+1) AS UNSIGNED) * 2.54 ) AS cm
FROM
inches;

Mysql POINT column for distance search

yes i know this question ever asked plenty of time but all seems outdated from 2012, base of thoses question/ansewers ,
i tried to perform the classic search distance with column POINT
but i have some trouble unresolvable..
is normal my POINT column looks like this ?
0x00000000010100000085B1852007052040C0B2D2A414684840
Here is all my steps, i am not able to see whats wrong,
i did based from last stack questions/answers.
I use mariadb 10 with Heideisql gui.
i have 2 colums lat and lon ,
i created a geopoints POINT column,
populate geopoint like this:
UPDATE geoFRA
SET geopoints = GeomFromText(CONCAT('POINT (', lon, ' ', lat, ')'))
After that my geopoints column looks like this :
0x00000000010100000085B1852007052040C0B2D2A414684840
Then i try to perform the query in 2 maners , first try :
SET#lat = 48.88;
SET#lon = 2.34;
SELECT *
FROM geoFRA
WHERE MBRContains(LineFromText(CONCAT(
'('
, #lon + 700 / ( 111.1 / cos(RADIANS(#lon)))
, ' '
, #lat + 700 / 111.1
, ','
, #lon - 700 / ( 111.1 / cos(RADIANS(#lat)))
, ' '
, #lat - 700 / 111.1
, ')' )
,geopoints)
and second try :
SET#lat = 48.88;
SET#lon = 2.34;
SET #kmRange = 172; -- = 50 Miles
SELECT *, (3956 * 2 * ASIN(SQRT(POWER(SIN((#lat - abs(`lat`)) * pi()/180 / 2),2) + COS(#lat * pi()/180 ) * COS(abs(`lat`) * pi()/180) * POWER(SIN((lon - `lon`) * pi()/180 / 2), 2)))) as distance
FROM `geoFRA`
WHERE MBRContains(LineString(Point(#lat + #kmRange / 111.1, #lon + #kmRange / (111.1 / COS(RADIANS(#lat)))), Point(#lat - #kmRange / 111.1, #lon - #kmRange / (111.1 / COS(RADIANS(#lat))))), `geopoints`)
Order By distance
I begin to think there is some mariadb incompatibility ?! or did i miss something?
thanks for any help..,
flau
CREATE TABLE geoFRA (id int NOT NULL, geopoints point NOT NULL);
INSERT INTO geoFRA (id, geopoints) VALUES
(1, geomFromText('POINT(48 2)')),
(2, geomFromText('POINT(48 3)')),
(3, geomFromText('POINT(48.88 2.34)')),
(4, geomFromText('POINT(49 2)')),
(5, geomFromText('POINT(49 3)'));
SET #p=geomFromText('POINT(48.88 2.34)');
SELECT X(geopoints), Y(geopoints), asText(geopoints), ST_Distance(geopoints, #p) as d
FROM geoFRA
ORDER BY d;
This returns the geopoints ordered by distance. Using geopoints without X(), Y() and asText() returns them in the Well-Known Binary (WKB) format: http://dev.mysql.com/doc/refman/5.7/en/gis-data-formats.html#gis-wkb-format

How To Generate A Random Decimal Value In Mysql

I am trying to generate a random value between 0.01 - 0.50 to enter into mysql. I have 2.7 million rows that I need to execute this on.
Here is my script:
UPDATE FBAInventory SET buyBox = ROUND( 0.01 + RAND( ) * 8,2 );
It is generating values such as 4.20, 3.89 etc. I only want it to span from 0.01 - 0.50 and not to exceed this.
Does anyone know how to do this?
Thanks!
How about...
round(rand() * 0.49 + 0.01, 2);
You can use the floor function to generate a range of random numbers.
FLOOR(RAND() * (<max> - <min> + 1)) + <min>
where the max and min are inclusive. So in your case you would want
FLOOR(RAND() * 1.49 ) + 0.01

MySQL weighted average in a single query

I have a MySQL table which looks like this:
id load_transit load_standby hours_transit hours_standby
1 40 20 8 4
2 30 15 10 10
3 50 10 3 9
I need to do the following calculations:
(intermediate calculations)
hours_transit_total = 8+10+3 = 21
hours_standby_total = 4+10+9 = 23
(desired result)
load_transit_weighted_mean = 40*(8/21) + 30*(10/21) + 50*(3/21) = 36.667
load_standby_weighted_mean = 20*(4/23) + 15*(10/23) + 10*(9/23) = 13.913
Is it possible to do this in a single query? What would the best design be?
Note that
40*(8/21) + 30*(10/21) + 50*(3/21) =
(40*8)/21 + (30*10)/21 + (50*3)/21 =
(40*8 + 30*10 + 50*3)/21
and
20*(4/23) + 15*(10/23) + 10*(9/23) =
(20*4)/23 + (15*10)/23 + (10*9)/23 =
(20*4 + 15*10 + 10*9)/23
Which allows you to get the results you want using
SELECT sum(hours_transit * load_transit) / sum(hours_transit),
sum(hours_standby * load_standby) / sum(hours_standby)
FROM your_table
I just had this same question and built this little query I think makes it clear how to find the weighted average in a single query:
select sum(balance), sum(rate * balance / 5200) as weighted_rate, -- what I want
-- what you cannot do: sum(rate * balance / sum(balance))
sum(balance * rate) / sum(balance) as weighted_rate_legit -- ah thank you transitive math properties
from (
select '4600' as balance, '2.05' as rate from dual
union all
select '600' as balance, '2.30' as rate from dual
) an_alias;

MySQL convert legacy decimal to milliseconds

I am working with some legacy tables that represent time as a decimal representating time like this:
74447.548 = 7:44:47.548
I am moving this to a table where time is stored as (int) milliseconds. I want to create a function for this conversion.. The following works, but is there a more efficient way??
CREATE FUNCTION `test`.`decimalToMilli` (bigTime decimal)
RETURNS INTEGER
BEGIN
return (floor(mod(bigTime,floor(bigTime))*1000) -- milliseconds
+ (floor(bigTime) MOD 100) * 1000 -- seconds
+ ((((floor(bigTime) - floor(bigTime) MOD 100) MOD 10000))/100) * 1000*60 -- minutes
+ ((((floor(bigTime) - floor(bigTime) MOD 10000) MOD 1000000))/10000) * 1000*60*60 --hrs
);
END
Suggestions for a better way?
What about this?
CREATE FUNCTION `test`.`decimalToMilli` (bigTime decimal)
RETURNS INTEGER
BEGIN
return ((bigTime * 1000) MOD 100000 -- seconds and milliseconds
+ (floor(bigTime / 100) MOD 100) * 60000 --minutes
+ (floor(bigTime / 10000)) * 3600000 -- hours
);
END