How to to insert floats into mysql and then query eqality - mysql

Wowee ..does mysql work with floats or not!
1) I insert a float into mysql field
price = 0.1
2) I run the below query:
select * from buy_test where price = 0.1
WOW! I get no results
3) I run the below query:
select * from buy_test where price < 0.1
I get no results
4) I run the below query
select * from buy_test where price > 0.1
YAY! I get results but no..I wanted where price =0.1
How to I insert a float to mysql so I can query a float in mysql
Thanks
CREATE TABLE `buy_test` (
`user_id` varchar(45) DEFAULT NULL,
`order_id` varchar(100) NOT NULL,
`price` float DEFAULT NULL,
`insert_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$

That's because 0.1 doesn't exist in floating point arithmetic.
It would take an infinity number of digits to print the real value of 0.1 in binary (just like it would take an infinity number of digits do print the real value of 10/3).
In your table, you are storing the price with a 'float' type, which is represented on 32 bits. The value 0.1 is rounded to 0.100000001490116119384765625 (which is the nearest representation of 0.1 in the float type format).
When you are requesting all rows where prices are equal to 0.1, I strongly suspect the interpreter to use the double type, or at least, a more precise type than float.
But let's consider it's using the double type on 64 bits.
In the double type, 0.1 is rounded to 0.1000000000000000055511151231257827021181583404541015625 .
When the engines makes the comparison, it leads to:
if (0.100000001490116119384765625 ==
0.1000000000000000055511151231257827021181583404541015625) ...
which is obviously false. But it's true for operator > .
I'm pretty sure that this where clause would work: "where price = 0.100000001490116119384765625"
By the way, when the result of your query tells you that the price is "0.1", it's a lie. The value is rounded to be "beautifully displayed".
There is no real solution to your problem, everybody knowing floating point arithmetic problems will discourage you to use equality comparison on floats.
You may use an epsilon for your request.
There is a very interesting article named "What Every Computer Scientist Should Know About Floating-Point Arithmetic"; you can find it there:
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Related

MySQL Workbench out of range value for decimal number

I wanted to create an table
create table Oceny_projekty
(
OProj_Id int not null comment '',
ID_Projektu int comment '',
ID_Studenta int comment '',
OProj_Ocena decimal(1,1) comment '',
OProj_Data date comment '',
primary key (OProj_Id)
);
And fill it with sample data generated by PowerDesigner
insert into Oceny_projekty (OProj_Id, ID_Projektu, ID_Studenta, OProj_Ocena, OProj_Data)
values (2, 18, 10, '2.5', '1857-12-25');
And I've got this:
insert into Oceny_projekty (OProj_Id, ID_Projektu, ID_Studenta,
OProj_Ocena, OProj_Data) values (2, 18, 10, '2.5', '1857-12-25') Error
Code: 1264. Out of range value for column 'OProj_Ocena' at row 1
How can I modify command that can accept decimal numbers? (with integer numbers there is no problem)
Using MySQL Workbench 6.3, PowerDesigner 16.6
Thanks in advance!
Declaring OProj_Ocena as decimal(1,1) means that it has 0 integer digits (precision - scale = 1 - 1 = 0) and 1 fractional digit. It can only store values 0, 0.1, 0.2 ... 0.9.
The datatype you need is probably decimal(2,1).
Putting Marek Grzenkowicz's answer in another way, DECIMAL(M, D):
M = D + (the number of whole number digits). See 12.25.2 DECIMAL Data Type Characteristics
So, determine the number of whole number digits you want, those to the left of the decimal point, and the number of decimal places (D) that you need and add them to get M. IMO, they should have used the phrase "whole number digits" or "integer digits" to make this a bit more obvious even though what they say means that as M is for ALL digits. I misinterpreted this at first until I reread their description a few times.

mySQL column without a one-size-fits-all precision for DECIMAL

When I define a table to store decimal values I use a statement like this:
CREATE TABLE myTable (
myKey INT NOT NULL,
myValue DECIMAL(10,2) NOT NULL,
PRIMARY KEY (myKey)
);
However, this results in every myValue being stored with a one-size-fits-all precision of (10,2). For instance
45.6 becomes 45.60
21 becomes 21.00
17.008 becomes 17.01
But what if each record has a myValue of different precision? I need 45.6 to remain 45.6, 21 to remain 21, and 17.008 to remain 17.008. Otherwise the precision of measurement is being lost. There's a big difference between 21 and 21.00.
If you don't need to do greater/less-than compares, store as a VARCHAR(..)
The strings '21' and '21.00' would have identical values, but present different "precision".
When needing the numeric value, add zero (col + 0).
This does not allow for "negative precision", such as "1.2M" being represented as 1200000. If you need that, then Norbert's approach is probably better.
You can store with high precision and exact recall by following a different way of storing the data:
Create a table with two columns:
CREATE TABLE precise (value BIGINT, decimaldot INT);
Use code to determine where the dot is, for example in your 21 value: 2 (assuming 1 indexing). So stored the value would be:
INSERT INTO precise values (21,2);
Retrieved it would return 21 exact (parsing back the dot in the value 21 at position 2, is 21)
Value 17.008 would also have decimaldot at 2:
INSERT INTO precise values (17008,2);
Etc..
Larger values can be stored by using a VARCHAR(4000) instead of a biginteger, or by using blob fields.

MySql Data size [duplicate]

What is the size of column of int(11) in mysql in bytes?
And Maximum value that can be stored in this columns?
An INT will always be 4 bytes no matter what length is specified.
TINYINT = 1 byte (8 bit)
SMALLINT = 2 bytes (16 bit)
MEDIUMINT = 3 bytes (24 bit)
INT = 4 bytes (32 bit)
BIGINT = 8 bytes (64 bit).
The length just specifies how many characters to pad when selecting data with the mysql command line client. 12345 stored as int(3) will still show as 12345, but if it was stored as int(10) it would still display as 12345, but you would have the option to pad the first five digits. For example, if you added ZEROFILL it would display as 0000012345.
... and the maximum value will be 2147483647 (Signed) or 4294967295 (Unsigned)
INT(x) will make difference only in term of display, that is to show the number in x digits, and not restricted to 11. You pair it using ZEROFILL, which will prepend the zeros until it matches your length.
So, for any number of x in INT(x)
if the stored value has less digits than x, ZEROFILL will prepend zeros.
INT(5) ZEROFILL with the stored value of 32 will show 00032
INT(5) with the stored value of 32 will show 32
INT with the stored value of 32 will show 32
if the stored value has more digits than x, it will be shown as it is.
INT(3) ZEROFILL with the stored value of 250000 will show 250000
INT(3) with the stored value of 250000 will show 250000
INT with the stored value of 250000 will show 250000
The actual value stored in database is not affected, the size is still the same, and any calculation will behave normally.
This also applies to BIGINT, MEDIUMINT, SMALLINT, and TINYINT.
According to here, int(11) will take 4 bytes of space that is 32 bits of space with 2^(31) = 2147483648 max value and -2147483648min value. One bit is for sign.
As others have said, the minumum/maximum values the column can store and how much storage it takes in bytes is only defined by the type, not the length.
A lot of these answers are saying that the (11) part only affects the display width which isn't exactly true, but mostly.
A definition of int(2) with no zerofill specified will:
still accept a value of 100
still display a value of 100 when output (not 0 or 00)
the display width will be the width of the largest value being output from the select query.
The only thing the (2) will do is if zerofill is also specified:
a value of 1 will be shown 01.
When displaying values, the column will always have a width of the maximum possible value the column could take which is 10 digits for an integer, instead of the miniumum width required to display the largest value that column needs to show for in that specific select query, which could be much smaller.
The column can still take, and show a value exceeding the length, but these values will not be prefixed with 0s.
The best way to see all the nuances is to run:
CREATE TABLE `mytable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`int1` int(10) NOT NULL,
`int2` int(3) NOT NULL,
`zf1` int(10) ZEROFILL NOT NULL,
`zf2` int(3) ZEROFILL NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `mytable`
(`int1`, `int2`, `zf1`, `zf2`)
VALUES
(10000, 10000, 10000, 10000),
(100, 100, 100, 100);
select * from mytable;
which will output:
+----+-------+-------+------------+-------+
| id | int1 | int2 | zf1 | zf2 |
+----+-------+-------+------------+-------+
| 1 | 10000 | 10000 | 0000010000 | 10000 |
| 2 | 100 | 100 | 0000000100 | 100 |
+----+-------+-------+------------+-------+
This answer is tested against MySQL 5.7.12 for Linux and may or may not vary for other implementations.
What is the size of column of int(11) in mysql in bytes?
(11) - this attribute of int data type has nothing to do with size of column. It is just the display width of the integer data type. From 11.1.4.5. Numeric Type Attributes:
MySQL supports an extension for optionally specifying the display
width of integer data types in parentheses following the base keyword
for the type. For example, INT(4) specifies an INT with a display
width of four digits.
A good explanation for this can be found here
To summarize : The number N in int(N) is often confused by the maximum size allowed for the column, as it does in the case of varchar(N). But this is not the case with Integer data types- the number N in the parentheses is not the maximum size for the column, but simply a parameter to tell MySQL what width to display the column at when the table's data is being viewed via the MySQL console (when you're using the ZEROFILL attribute).
The number in brackets will tell MySQL how many zeros to pad incoming integers with. For example: If you're using ZEROFILL on a column that is set to INT(5) and the number 78 is inserted, MySQL will pad that value with zeros until the number satisfies the number in brackets. i.e. 78 will become 00078 and 127 will become 00127. To sum it up: The number in brackets is used for display purposes.
In a way, the number in brackets is kind of usless unless you're using the ZEROFILL attribute.
So the size for the int would remain same i.e., -2147483648 to 2147483648 for signed and 0 to 4294967295 for unsigned (~ 2.15 billions and 4.2 billions, which is one of the reasons why developers remain unaware of the story behind the Number N in parentheses, as it hardly affects the database unless it contains over 2 billions of rows), and in terms of bytes it would be 4 bytes.
For more information on Integer Types size/range, refer to MySQL Manual
In MySQL integer int(11) has size is 4 bytes which equals 32 bit.
Signed value is : -2^(32-1) to 0 to 2^(32-1)-1
= -2147483648 to 0 to 2147483647
Unsigned values is : 0 to 2^32-1
= 0 to 4294967295
Though this answer is unlikely to be seen, I think the following clarification is worth making:
the (n) behind an integer data type in MySQL is specifying the display width
the display width does NOT limit the length of the number returned from a query
the display width DOES limit the number of zeroes filled for a zero filled column so the total number matches the display width (so long as the actual number does not exceed the display width, in which case the number is shown as is)
the display width is also meant as a useful tool for developers to know what length the value should be padded to
A BIT OF DETAIL
the display width is, apparently, intended to provide some metadata about how many zeros to display in a zero filled number.
It does NOT actually limit the length of a number returned from a query if that number goes above the display width specified.
To know what length/width is actually allowed for an integer data type in MySQL see the list & link: (types: TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT);
So having said the above, you can expect the display width to have no affect on the results from a standard query, unless the columns are specified as ZEROFILL columns
OR
in the case the data is being pulled into an application & that application is collecting the display width to use for some other sort of padding.
Primary Reference: https://blogs.oracle.com/jsmyth/entry/what_does_the_11_mean
according to this book:
MySQL lets you specify a “width” for integer types, such as INT(11).
This is meaningless for most applications: it does not restrict the
legal range of values, but simply specifies the number of characters
MySQL’s interactive tools will reserve for display purposes. For
storage and computational purposes, INT(1) is identical to INT(20).
I think max value of int(11) is 4294967295
4294967295 is the answer, because int(11) shows maximum of 11 digits IMO

Cast as decimal in mysql

I have below table structure and data :
create table sample
(
id INT(10)
);
INSERT INTO sample
values
(23398),
(98743),
(54734);
Now I want to understand CAST function in mysql. Consider following query :
select
cast((id/3) as decimal(2,2)) as cast1,
cast((id/3) as decimal(3,2)) as cast2,
cast((id/3) as decimal(4,2)) as cast3,
cast((id/3) as decimal(5,2)) as cast4,
cast((id/3) as decimal(6,2)) as cast5,
cast((id/3) as decimal(7,2)) as cast6,
id/3 as actualId
from sample;
Please see output of this query at SQL Fiddle.
I am wondering why this query gives 0.99, 9.99 and vice versa.
Can anyone explain it ?
Thanks in advance.
decimal is a type that takes 2 arguments
decimal(size, places) :
size determines how many digits are in the number.
places determines how many of those digits are to the right of the decimal.
decimal(2,2) - .00 - 2 digits both of which are to the right of the decimal
when casting (23398 / 3) = 7799.33333333 to declimal(2, 2) it yields a decimal in the specified amount of space closest to the desired number which is 0.99
decimal(3,2) - 0.00 - 3 digits 2 of which are to the right of the decimal
when casting (23398 / 3) = 7799.33333333 to declimal(3, 2) it yields a decimal in the specified amount of space closest to the desired number which is 9.99
if all of the original numbers were negative you would yield -0.99 and -9.99 because they are the closest numbers to the desired number within the allocated space
As a matter of fact java does something similar if you take the max double and try to convert it to an int you will give the max int which is no where near the max double

Improving select speed - mysql - very large tables

Newbie to MySQL and SQL in general - so please be gentle :-)
I have a table with a very high number of rows. The table is:
create table iostat (
pkey int not null auto_increment,
serverid int not null,
datestr char(15) default 'NULL',
esttime int not null default 0,
rs float not null default 0.0,
ws float not null default 0.0,
krs float not null default 0.0,
kws float not null default 0.0,
wait float not null default 0.0,
actv float not null default 0.0,
wsvct float not null default 0.0,
asvct float not null default 0.0,
pctw int not null default 0,
pctb int not null default 0,
device varchar(50),
avgread float not null default 0.0,
avgwrit float not null default 0.0,
primary key (pkey),
index i_serverid (serverid),
index i_esttime (esttime),
index i_datestr (datestr),
index i_rs (rs),
index i_ws (ws),
index i_krs (krs),
index i_kws (kws),
index i_wait (wait),
index i_actv (actv),
index i_wsvct (wsvct),
index i_asvct (asvct),
index i_pctb (pctb),
index i_device (device),
index i_servdate (serverid, datestr),
index i_servest (serverid, esttime)
)
engine = MyISAM
data directory = '${IOSTATdatadir}'
index directory = '${IOSTATindexdir}'
;
Right now the table has 834,317,203 rows.
Yes - I need all the data. The highest level organization of the data is by the collection date (datestr). It is a CHAR instead of a date to preserve the specific date format I use for the various load, extract, and analysis scripts.
Each day adds about 16,000,000 rows.
One of the operations I would like to speed up is (Limit is generally 50 but ranges from 10 to 250):
create table TMP_TopLUNsKRead
select
krs, device, datestr, esttime
from
iostat
where
${WHERECLAUSE}
order by
krs desc limit ${Limit};
WHERECLAUSE is:
serverid = 29 and esttime between X and Y and device like '%t%'
where X and Y are timestamps spanning anywhere from 4 minutes to 24 hours.
I'd prefer to not change the DB engine. This lets me put data and indexes on separate drives which gave me significant overall performance. It's also a total of 1.6 billion rows, which would take an insane amount of time to reload.
device like '%t%'
This is the killer. The leading % means it is a search of the whole column, or index if it's indexed, not an index lookup. See if you can do without the leading %.
Without knowing what's in your ${WHERECLAUSE} it's impossible to help you. You are correct that this is a huge table.
But here is an observation that might help: A compound covering index on
(krs, device, datestr, esttime)
might speed up the ordering and extraction of your subset of data.