Rounding mysql 0.5 doesn't always go up - mysql

https://i.stack.imgur.com/pxEQW.png
CREATE TABLE `zz` (
`jum_r` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `zz` VALUES (71045),(31875),(12045),(172125),(27325),(5465);
SELECT
jum_r,
ROUND(ROUND((jum_r * 1.1), 2), 2) as q_gross,
ROUND(jum_r * 1.1) as gross,
ROUND((jum_r * 10 / 100), 2) as q_ppn,
ROUND(jum_r * 10 / 100) as ppn
FROM zz;
I have data according to the picture. Why does rounding 0.5 not always go up ...? What's wrong with my query? Thanks

For exact-precision numbers (e.g. DECIMAL) MySQL rounds 0.5 up to the next highest integer. For imprecise numbers (e.g. FLOAT) MySQL counts on the underlying C library's rounding, which is often "round-to-even". Doc ref here

After clarifying below, this should be your answer:
CASE would help. Basically:
WHEN (ROUND(jum_r * 1.1) < 0.5) THEN FLOOR(ROUND(jum_r * 1.1)), WHEN (ROUND(jum_r * 1.1) >= 0.5 THEN CEILING(ROUND(jum_r * 1.1)). Not pretty but should work

Related

How to get correct format on SQL calculations within SP

Beneath you can see some calculations i am doing for my business within a big SP. I will just post a line of it here. The problem is that i cannot get the format right. It is supposed to be like this:
CONVERT(DECIMAL(30, 2), ( isa.sales_price * 0.8) * (1 - u.discount) ) as PRICE
Example of result:
The isa.sales_price is: 149
The u.discount is: 24
The result is: -2741.60
What am i doing wrong?
EDIT, here is the result after some help:
CONVERT(DECIMAL(30, 2), ( isa.sales_price * 0.8) * (1-(u.rabatt/100)) )
What is wrong - I suspect - is that the calculation isn't what you expect it to be:
149 * 0.8 * (1 - 24) does indeed return -2741.60
Why do you expect it to give you something else?
If I were to venture a guess, you should divide discount with 100 as it's likely a percent value. But that's a guess.

Different result for Haversine formulas

I am using mysql to count the proximity and for that i have created one procedure named distance which is as follows but that procedure is not working properly but the sql statement is working so what is the difference over here as both are i guess Haversine formulas but not giving me the proper result. i really don't know wht i am missing in formula one.
Data structure of my table is as follows
for formula one
id varchar(100)
userid varchar(100)
username varchar(100)
currLoc point
radius int(10)
for formula two
id varchar(30)
userid varchar(30)
username varchar(40)
lat float(10,6)
lan float(10,6)
radius varchar(100)
Formula One: reference
sql statement to execute distance function
SELECT userid, username, distance(userstatus.currLoc,
GeomFromText('POINT(23.039574 72.56602)')) AS cdist
FROM userstatus HAVING cdist <= 0.6 ORDER BY cdist LIMIT 10
RETURN 6371 * 2 *
ASIN( SQRT(POWER(SIN(RADIANS(ABS(X(a)) - ABS(X(b)))), 2) +
COS(RADIANS(ABS(X(a)))) * COS(RADIANS(ABS(X(b)))) *
POWER(SIN(RADIANS(Y(a) - Y(b))), 2)));
Formula two: reference
SELECT *,(((acos(sin((23.039574*pi()/180)) *
sin((lat *pi()/180))+cos((23.039574*pi()/180)) *
cos((lat *pi()/180)) * cos(((72.56602- lon)*pi()/180))))*
180/pi())*60*1.1515*1.609344) as distance
FROM status HAVING distance <= 0.6
here 0.6 is a radius in kilometers
One version of the expression is using ABS(X(a)) etc and the other is not. The one using ABS is suspect. You can't afford to ignore the sign on the angles. You'll get different results in some areas of the world (near the equator or the prime meridian, for example, or near the poles).
Your constants are also different.
60*1.1515*1.609344
vs
6371 * 2
One expression involves SQRT, the other does not.
One expression involves ASIN and the other uses ACOS.
There is essentially nothing in common between the two...
See the discussion at Wikipedia 'Haversine Formula', and in particular the references to numerical stability when the distance between the points is small.
You could also improve the chances of people helping you by making the formulae you're using semi-readable, by splitting them over lines.
For example:
RETURN 6371 * 2 *
ASIN( SQRT(POWER(SIN(RADIANS(ABS(X(a)) - ABS(X(b)))), 2) +
COS(RADIANS(ABS(X(a)))) * COS(RADIANS(ABS(X(b)))) *
POWER(SIN(RADIANS(Y(a) - Y(b))), 2)));
And:
(((acos(sin((23.039574*pi()/180)) * sin((lat *pi()/180)) +
cos((23.039574*pi()/180)) * cos((lat *pi()/180)) *
cos(((72.56602-lan)*pi()/180))
)
) * 180/pi()) * 60 * 1.1515 * 1.609344)
The latter references 'lan'; is that meant to be 'lon'? In the second example, you appear to have encoded one of the two positions as 23.039574°N and 72.56602°W, and lat and lan come from the table in the SQL query.

MySQL - how to round

I have this in one of my queries:
FORMAT(ROUND(AVG(`rating` * 2)) / 2, 1) AS `average_rating`
If rating has a value of, say, 1.45 - then I get 1.5, which is what I want. When it rounds to whole numbers, I get 1.0, 2.0, etc. I don't want that. When I get whole numbers, I'd like to drop the decimal value.
Is there a way to do this in MySQL?
Try in this way :
(TRIM(TRAILING '.' FROM(CAST(TRIM(TRAILING '0' FROM
FORMAT(ROUND(AVG(`rating` * 2)
) / 2, 1))AS char)))) AS `average_rating`

MySQL query performance tuning

I'm trying to run a query over a table with around a 1 million records.
The structure of the table with its indexes is:
CREATE TABLE `table` (
`Id` int(11) NOT NULL,
`Name` varchar(510) DEFAULT NULL,
`Latitude` float NOT NULL DEFAULT '0',
`Longitude` float NOT NULL DEFAULT '0',
PRIMARY KEY (`Latitude`,`Longitude`,`Id`),
KEY `IX_Latitude_Longitude` (`Latitude`,`Longitude`),
KEY `IX_Latitude` (`Latitude`),
KEY `IX_Longitude` (`Longitude`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I'm running the following query:
SELECT m.Id, m.Name, sqrt(69.1 * (m.Latitude - :latitude) * 69.1 * (m.Latitude - :latitude) +
53.0 * (m.longitude - :longitude) * 53.0 * (m.longitude - :longitude)) as Distance,
m.Latitude as Latitude, m.Longitude as Longitude
FROM table m
WHERE sqrt(69.1 * (m.Latitude - :latitude) * 69.1 * (m.Latitude - :latitude)
+ 53.0 * (m.longitude - :longitude) * 53.0 * (m.longitude - :longitude)) < :radius
ORDER BY sqrt(69.1 * (m.Latitude - :latitude) * 69.1 * (m.Latitude - :latitude) +
53.0 * (m.longitude - :longitude) * 53.0 * (m.longitude - :longitude)) desc
LIMIT 0, 100
That suppose to return all the records in a specific radius (distance calculation information: http://www.meridianworlddata.com/Distance-Calculation.asp)
BUT the query takes a lot of time...
Here is the explain plan that I get:
id|select_type |table|type|possible_keys|key |key_len|ref |rows |Extra
1 |SIMPLE |m |ALL |{null} |{null}|{null} |{null}|1264001|Using where; Using filesort
What am I doing wrong?
Which index do I need to add in order to cause the query to use it instead of table scan?
Do I need to change the table structure?
You're using functions inside your WHERE clause, so it will always result in a table scan. The database has no way to index against the result of a function. I think your best option is to come up with some way to limit the results before trying to evaluate the distance algorithm.
For instance, for a given location, you can know the minimum and maximum possible latitude that can fall within your set distance, so filter by that first. A degree of latitude is ~69 miles, so if your search radius is 50 miles, it would never be possible for anything more than 0.725 degrees of latitude away to fall within 50 miles of your location. Since this is just a numeric comparison WHERE m.latitude > (:latitude - 0.725) AND m.latitude < (:latitude + 0.725), not a call to a function, the database will be able to use your indexes to evaluate it.
Longitude is more complicated, since the distance for each degree varies depending on how far north/south the location happens to be, but depending on how much work you want to put into it, you could do the same with longitude as well.

Selecting an int and dividing using MYSQL

How do I select an int, then divide it by 100 using MYSQL?
Select (field / 100) as divided
From Table;
Simple divide. The question is, do you want integer arithmetic?
For example, 163 / 100 = 1. So you need to convert it implicitly or explicitly first to get 1.63
SELECT MyColumn * 1.0 / 100 FROM MyTable
or
SELECT MyColumn / 100.0 FROM MyTable
Try this sql query:
SELECT 16800 /* = an int */ / 100