Syed Khan Syed Khan - 4 months ago 10
MySQL Question

Mysql where clause not working for all values

I am having trouble with mysql where clause, I have a table, with 3 fields, OutputValue, FromValue and ToValue, it basically compares both values with a number and returns its OutputValue.

this is my table sql

CREATE TABLE IF NOT EXISTS `value_scale` (
`OutputValue` varchar(50) NOT NULL,
`FromValue` float NOT NULL,
`ToValue` float NOT NULL,
PRIMARY KEY (`OutputValue`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `value_scale` (`OutputValue`, `FromValue`, `ToValue`) VALUES
('L', 0.11, 0.3),
('L1', 0.31, 0.5),
('L2', 0.51, 0.7),
('L3', 0.71, 1.99),
('L4', 2, 2.99),
('L5', 3, 9999),
('P', -0.3, -0.11),
('P1', -0.5, -0.31),
('P2', -0.7, -0.51),
('P3', -1.99, -0.71),
('P4', -2.99, -2),
('P5', -9999, -3),
('S', -0.1, 0.1);


when the target value is not equal to value in FromValue or ToValue, it shows results, else no output is shown

my query is

SELECT * from value_scale where -0.31 between FromValue and ToValue


it works for -0.32 and -0.3 but not for -0.31

even if I search for value in ToValue column, no output is shown, forexample there is a row (P1, -0.5, -0.31)

SELECT * FROM value_scale WHERE tovalue = -0.31


even this query shows 0 rows

Answer

This is a representation of numbers problem. Floating point is approximate. That means that what you see is not what you get. So, -0.31 could really be -0.309999999997 or something like that.

The best solution is to fix the table. You seem to want two decimal places, so use decimal for the data type:

CREATE TABLE IF NOT EXISTS `value_scale` (
  `OutputValue` varchar(50) NOT NULL,
  `FromValue` decimal(10, 2) NOT NULL,
  `ToValue` decimal(10, 2) NOT NULL,
  PRIMARY KEY (`OutputValue`)
) ;

If you already have the table, you can alter it in place:

alter table value_scale alter column FromValue decimal(10, 2);
alter table value_scale alter column ToValue decimal(10, 2);

I should also mention, that you should probably have boundaries such as:

0.10 - 0.30
0.30 - 0.50

and so on. Then, don't use between. Use:

where $val >= FromValue and $val < ToValue

This prevents a problem such as 0.305 from not matching a row.