I have the following table:
CREATE TABLE `ages` (
`id` tinyint(3) UNSIGNED NOT NULL,
`min_age` decimal(4,2) NOT NULL,
`max_age` decimal(4,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
With the following data:
INSERT INTO `ages` (`id`, `min_age`, `max_age`) VALUES
(1, 4.00, 4.30),
(2, 4.40, 4.70),
(3, 4.80, 4.11),
(4, 5.00, 5.50),
(5, 5.60, 5.11),
(6, 6.00, 6.50),
(7, 6.60, 6.11),
(8, 7.00, 7.50),
(9, 7.60, 7.11),
(10, 8.00, 8.11),
(11, 9.00, 9.11),
(12, 10.00, 10.11),
(13, 11.00, 11.11),
(14, 12.00, 12.11),
(15, 13.00, 13.11),
(16, 14.00, 14.11),
(17, 15.00, 24.11);
You can find a fiddle here to run and test queries directly: https://www.db-fiddle.com/f/qkbkZD2kWjpPtyv4TiZN23/0
I’m trying to get some recorde based on min_age
and max_age
columns but no results are returned.
Select example:
SELECT * FROM `ages`
WHERE `min_age` <= 8.6 AND `max_age` >= 8.6;
It’s not working becuase the condition should match this row:
id | min_age | max_age |
---|---|---|
10 | 8.00 | 8.11 |
in this case 8.11 is smaller than 8.6 because this fraction represents the number of months, so I want 8.11 to be the bigger value.
How to make it work and return row with id
= 10?
2
Answers
This realy doesn’t make sense, but just to point to some of the issues I’ll answer the question with code that works with the data provided. Hope the issues will be clear and that years and months as a decimal number will be escaped one way or another – for good!
… with this sample data you tryed to select the row with id = 10 using this Where clause :
… where 8.6 is 8 years and 6 months – if that is so you should extract years and months out of both min_age and max_age columns – for that you could (with an exception) create a cte like this …
… now you have nice and shiny integer values for years and months – BUT there is exception (mentioned in comments) – if you can make distinction between e.g. 6 year and 1 month vs 6 years and 10 months written as a decimal in the database then you handle that too in the code above cause it doesn’t cope (with current syntax) with this kind of exception …
… let’s forget the exception and see how to use the above code to select the row with id = 10 using 8.6 decimal presented as years.months …
… if your 8.6 is 8 years and 6 months then you’ll need to use OR operator twice to filter the sample data by logic described …
See the fiddle here.
Remember: you’re working decimal values, which is not exactly the same as two integers separated by a period, because the decimal value as implies a specific denominator.
It helps to understand if we emphasize the "fraction" part of the quote. When viewed as a fraction,
8.6
is and always will be 8 and 6/10ths, which is equivalent to 8 and 60/100ths. But the 8.11 value for themax_age
column is only 8 and 11/100ths. 11 is not >= 60, and so the row does not and cannot match the conditional expression.If you expected to have the
6
in8.6
only mean6
hundredths, instead of60
, you need to write it that way. Given these are months, where you have a max value of 11 (12 would be the next year), you can do it by using a leading0
in each of the decimal values 9 and below, (ie:8.06
). Looking at another row,(4, 5.00, 5.50)
should be encoded as(4, 5.00, 5.05)
. For other kinds of data, with larger potential maximum values, you may need more leading zeros.Or you could store the absolute number of months as an integer (96, 102, and 107 for 8.00, 8.06, and 8.11 respectively), so the
(4, 5.00, 5.50)
row would be encoded as(4, 60, 65)
.