SQL correct definition of floating points - mysql

I am measuring some values over a geo-location
I need to create a table that consists of:
date
longitude
latitude
value
The date column is the date of the measure,
The value is just an int value of the measure,
the longitude and latitude are a coordinates - they are floating points columns with 3 digits before the point and 5 after (i.e. *.*)
I'm wondering how to define my table, I try to use:
CREATE TABLE `obs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` date DEFAULT NULL,
`lon` decimal(5,5) DEFAULT NULL,
`lat` decimal(5,5) DEFAULT NULL,
`val` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Here is a link to sqlFiddle
But When I'm trying to run
INSERT INTO `obs` VALUES (null,'2014/06/07','34.000','31.342',1)
I am getting the following error:
Out of range value for column 'lon' at row 1:
Can anyone explain me what's wrong?

decimal(5,5) means
5 decimal places in TOTAL
5 decimal places after the point
That would make all numbers invalid having a decimal place before the point.
You probably want
decimal(10,5)

Related

mysql8 nearest place using radius filter

First of all, I am using mysql8.
I have a table that store states of my country.
My table ddl is:
CREATE TABLE state_v2(
`id` int(11) NOT NULL,
uf_code INT NULL,
uf VARCHAR(2) NOT NULL,
`name` VARCHAR(100) NOT NULL,
latitude FLOAT(8) NOT NULL,
longitude FLOAT(8) NOT NULL,
`country` varchar(75) NOT NULL,
coord POINT SRID 4326 NOT NULL,
PRIMARY KEY (id),
unique (country, uf_code),
unique (latitude, longitude),
index (uf_code)
);
ALTER TABLE state_v2 ADD SPATIAL INDEX(coord);
The user choose a place and I use this place as reference to find the nearest state less then 100km. (the parameter is a correct point).
I am using this query:
SELECT * FROM (
SELECT
sv.*,
ST_distance_sphere(
$param,
sv.coord) as distance
FROM state_v2 sv
WHERE ST_distance_sphere(
$param,
sv.coord) < 100000
) as temp
order by temp.distance;
1 - Is it correct this query? I am worried about the performance of using like that, it is using full table scan.
2 - Is it correct the created indexes?

mass update mysql table decimal value and change column field type

Currently the balance_amount column in MySQL is using double type, and it contains values such as 11.28839999999999.
I want to round such values to 2 decimal places to become 11.29, and I want to run a mass update to all the other 80 tables in the system so that it will show 2 decimal places only. After which, I want to change it from double to decimal (10,2) type.
CREATE TABLE IF NOT EXISTS `account` (
`account_id` varchar(15) NOT NULL,
`description` varchar(100) DEFAULT NULL,
`balance_amount` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
So how can I achieve it?
You can round the corresponding columns in each table to 2 decimal places using:
Update <table-name> SET <column-name> = ROUND(<column-name>, 2);
Then alter the corresponding column in each table to be a DECIMAL(10, 2):
ALTER TABLE `<table-name>` CHANGE COLUMN `<column-name>` `<column-name>` DECIMAL(10,2) NULL DEFAULT NULL ;
But this is something you should be doing in your maintenance window, not live hours and you should backup your database as a disaster management measure before doing this.

How to use in db MySQL decimal?

I need insert in the table tbl_range of my MySQL database this decimal value:
1866752.0
And I set field 'range' in the table tbl_range:
CREATE TABLE `tbl_range` (
`Range` decimal(10,5) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
But in the query insert I've this error:
[Err] 1264 - Out of range value for column 'Range' at row 1
You have to change:
Range decimal(10,5) DEFAULT NULL,
to
Range decimal(15,5) DEFAULT NULL,
because 1st parameter indicates total number of digits including decimal values. So if you are putting (10,5) then you can insert upto 99999.99999. But your required value is greater than that.
DECIMAL(X,Y): X = Number of total digits. Y = Number of digits after the decimal point.
Since you declare it DECIMAL(10,5) your maximum number is 99999.99999, a bit smaller than the number you're trying to insert.
Increase the first number a bit, depending on how big numbers you want to be able to handle in your table, or perhaps decrease the second one. Do you really need 5 digits after the decimal point?

MySql How to convert varchar (latitude, longitude) to Decimal fields?

In mysql I have a varchar containing latitude and longitude provided by Google maps.
I need to be able to query based on a bounding box value, but have no need for the geo features now available. I'm trying to populate 2 new Decimal fields with the Decimal values found in the varchar. Here is the query that I'm trying to use, but the result are all rounded values in the new fields.
Sample data:
'45.390746926938185, -122.75535710155964',
'45.416444621636415, -122.63058006763458'
Create Table:
CREATE TABLE IF NOT EXISTS `cameras` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(75) NOT NULL,
`position` varchar(75) NOT NULL,
`latitude` decimal(17,15) default NULL,
`longitude` decimal(18,15) default NULL,
`address` varchar(75) NOT NULL,<br />
`date` varchar(11) NOT NULL,<br />
`status` int(1) NOT NULL default '1',
`duplicate_report` int(11) NOT NULL default '0',
`missing_report` int(11) NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1050 ;
SQL:
UPDATE cameras
SET latitude = CAST( (substring(position,1,locate(',',position))) AS DECIMAL(17,15) ),
longitude = CAST( (substring(position,locate(',',position)+1)) AS DECIMAL(18,15) )
SQL Alternate attempt:
UPDATE cameras
SET latitude = CONVERT( (substring(position,1,locate(',',position))), DECIMAL(17,15) ),
longitude = CONVERT( (substring(position,locate(', ',position)+1)), DECIMAL(18,15) )
The resulting field values are for both scenarios:
45.000000000000000 and -122.000000000000000
AND
45.000000000000000 and -122.000000000000000
Can anyone see what I'm doing wrong?
Thanks.
Both the CAST and CONVERT forms seem to be correct.
SELECT CAST((SUBSTRING(t.position,1,LOCATE(',',t.position))) AS DECIMAL(17,15)) AS lat_
, CONVERT(SUBSTRING(t.position,LOCATE(', ',t.position)+1),DECIMAL(18,15)) AS long_
FROM (SELECT '45.390746926938185, -122.75535710155964' AS `position`) t
lat_ long_
------------------ ----------------------
45.390746926938185 -122.755357101559640
I think position is a reserved word, but I don't think that matters in this case. But it wouldn't hurt to assign a table alias and qualify all column references
UPDATE cameras c
SET c.latitude = CAST((SUBSTRING(c.position,1,LOCATE(',',c.position))) AS DECIMAL(17,15))
, c.longitude = CAST((SUBSTRING(c.position,LOCATE(',',c.position)+1)) AS DECIMAL(18,15))
But I suspect that won't resolve the problem.
One thing to check is for a before or after update trigger defined on the table, which is rounding/modifying the values assigned to the latitude and longitude columns?
I suggest you try running just a query.
SELECT CAST((SUBSTRING(c.position,1,LOCATE(',',c.position))) AS DECIMAL(17,15)) AS lat_
, CAST((SUBSTRING(c.position,LOCATE(',',c.position)+1)) AS DECIMAL(18,15)) AS lon_
FROM cameras c
and verify that produces the decimal values you expect.
A dot character should be recognized as a decimal point. Does the position column contain some other special characters, like a space or something?
From what you posted, it looks like the CAST and CONVERT working on the integer portion up to the decimal point. (There shouldn't be an implicit convert to signed integer in there, so it's not clear why the characters following the decimal point aren't being included.)
If you can figure out what character(s) are being used to represent the decimal point, then you could use a MySQL REPLACE() function to replace those with a simple dot character.

MySQL GIS / Spatial Extensions - melting my brain

I'm new to GIS in MySQL and it's melting my brain!
I've created a table "places" as so:
CREATE TABLE `places` (
`id` int(6) unsigned zerofill NOT NULL auto_increment,
`business_name` varchar(100) NOT NULL,
`street_postcode` varchar(10) NOT NULL,
`longitude` decimal(22,20) NOT NULL,
`latitude` decimal(22,20) NOT NULL,
`coord` point NOT NULL,
UNIQUE KEY `id` (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=25080 DEFAULT CHARSET=utf8
id, business_name and street_postcode where inserted into the table
I then updated the table with longitude and latitude coordinates in PHP as so:
UPDATE `places` SET `longitude` = '".$longitude."', `latitude` = '".$latitude."', `coord` = GeomFromText('POINT(".$coord.")') WHERE `id` = '".$row->id."' LIMIT 1
This all seems to have gone well, but I'm stuck when trying to find the nearest place to X coordinates. How do I find the 10 nearest places to X longitude and latitude?
This does not seem to work:
SELECT business_name, street_postcode, ROUND(GLength(LineStringFromWKB(LineString(AsBinary(coord), AsBinary('51.49437081 -0.2275573')))))
AS distance FROM places ORDER BY distance ASC LIMIT 10;
Eternal thanks in advance!
That is because the spatial functions are not really implmented in MySQL. They stubbed out all the code but have not implemented all the methods.
I recommend using PostGIS or SpatiaLite.