SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 04.02.2011 01:07:01

ebuilder
Участник
Зарегистрирован: 04.02.2011
Сообщений: 7

Проблема с SELECT

Здравствуйте,

в таблице (7800 элементов) есть 2 поля тип "float"

поле `pcdd`, значения рядов (для примера):

"100"
"110"
"114.3"

Запрос: SELECT * FROM `table` WHERE `pcdd` = 114.3    - "ноль рядов"  !!!
Запрос: SELECT * FROM `table` WHERE `pcdd` = 100    - "1 ряд"
Запрос: SELECT * FROM `table` WHERE `pcdd` LIKE 114.3   - "1 ряд"

Вопрос, почему не ищет точно по значению "114.3" ?


Помогите пожалуйста, всю голову уже сломал...

PS База во вложении


Прикрепленные файлы:
Attachment Icon catalog.sql.gz, Размер: 152,448 байт, Скачано: 700

Неактивен

 

#2 04.02.2011 02:27:22

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Проблема с SELECT

Это особенность представления чисел в компьютере, связанная с округлением.

Например,

Код:

[silentia] root (none) > SELECT 2/3, 2/3 - 0.6667, 2/3 = 0.6667;
+--------+--------------+--------------+
| 2/3    | 2/3 - 0.6667 | 2/3 = 0.6667 |
+--------+--------------+--------------+
| 0.6667 |       0.0000 |            0 |
+--------+--------------+--------------+
1 row in set (0.00 sec)

С одной стороны, компьютер округляет 2/3 до 0.6667 и разность чисел
равна нулю. Но на самом деле она нулю не равна (там шесть в периоде),
и поэтому числа не равны. Различаются они каким-то знаком, который
мы уже не видим, но который есть.

При сравнении FLOAT и DOUBLE есть одно правило: через равенство их
сравнивать нельзя.

Неактивен

 

#3 04.02.2011 12:31:34

ebuilder
Участник
Зарегистрирован: 04.02.2011
Сообщений: 7

Re: Проблема с SELECT

В принципе, это все объясняет.

Тогда другой вопрос, кокой тип поля использовать для хранения этих значений чтобы потом делать выборку через равенство?

Отредактированно ebuilder (04.02.2011 13:31:13)

Неактивен

 

#4 04.02.2011 18:39:47

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Проблема с SELECT

Дело не в типе поля. Как Вы считаете — нужно ли выводить строку
WHERE `pcdd` = 114.3001? а `pcdd` = 114.3000000000000000000000001?

Неактивен

 

#5 05.02.2011 01:06:33

ebuilder
Участник
Зарегистрирован: 04.02.2011
Сообщений: 7

Re: Проблема с SELECT

Ну к примеру если у меня значения строк:

100
114
114.3
115
139.7
148

мне нужно отобрать 1 строку которая к примеру, именно 114.3 или 139.7, как быть? возможно через ROUND запрос строить?

Неактивен

 

#6 05.02.2011 13:58:28

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Проблема с SELECT

Для такого хранения данных можно использовать, например, BETWEEN 114.25 AND 114.34.

А что Вы храните в этой колонке, если не секрет, что по ней приходится искать?

Неактивен

 

#7 05.02.2011 14:18:45

ebuilder
Участник
Зарегистрирован: 04.02.2011
Сообщений: 7

Re: Проблема с SELECT

Это параметры автомобильных дисков, в данном случае расстояние между отверстиями под болты.

Мне нужно выбрать например все диски с такими параметрами из 1 таблицы:

7J16, 4x114.3, ET40, DIA73.1

т.е.
7 - ширина диска
16 - диаметр
4 - количество болтов
114.3  - расстояние между болтами
40 - вылет диска
73.1 - размер ступицы

И все это мне нужно поместить в 1 запрос

SELECT * FROM `table` WHERE `w`= '7' AND `D`= '16' AND `pcdc`= '4' AND `pcdd`= '114.3' AND `ET`= '40'  AND `DIA`= '73.1'  - разумеется не работает

Ну вот, `w`-ширина и `pcdd`-расстояние между дырками и `ET` - вылет и `DIA`- размер ступицы  - все они типа FLOAT)

Как будет выглядеть такой запрос?

Менять тип поля всетаки не вариант, так как придется еще поля сравнивать > и <  - для некоторых выборок..

вот такой вариант попробовал:
SELECT * FROM `table` WHERE ROUND(w, 2)= 7 AND ROUND(D, 2)= 16 AND ROUND(pcdc, 2)= 4 AND ROUND(pcdd, 2)= 114.3 AND ROUND(ET, 2)= 40 AND ROUND(DIA, 2)= 73.1   - работает, но выглядит страшновато, и вопрос потери в производительности....

Корректно ли это?


Вообще, между нами говоря я как и многие, стал жертвой математических законов) На самом деле, "не целые" значения полей для данной задачи имеют тот же смысл что и "целые", просто уж так вышло что они "не целые". В итоге теперь такой геморой.

Отредактированно ebuilder (06.02.2011 12:43:30)

Неактивен

 

#8 06.02.2011 13:20:28

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Проблема с SELECT

Вот последний абзац мне нравится у Вас больше всего. Вы действительно обращаетесь
с этими значениями как с целыми — так и храните их как целые (1143, например)? А
запятую перед последней цифрой просто добавляйте при выдаче.

Никогда не думал, что расстояние между болтами выставляется с точностью до десятых
долей миллиметра... там правда такая точность нужна?

Неактивен

 

#9 06.02.2011 13:31:21

ebuilder
Участник
Зарегистрирован: 04.02.2011
Сообщений: 7

Re: Проблема с SELECT

К сожалению, вариант умножения всех значений в колонке на 10 - неподходит, т.е. есть значения до 100тых, ныпример 107,95

(11430, 10795, ...) - придется умножать все на 100 и делать поле integer, и опять же как потом сравнивать < >  ...

>Никогда не думал, что расстояние между болтами выставляется с точностью до десятых
>долей миллиметра... там правда такая точность нужна?

думаю что точность до 100 долей и не оч нужна, но к сожалению приходится считаться с общепринятыми техническими характеристиками..

Все-таки, склоняюсь к варианту:
SELECT * FROM `table` WHERE ROUND(w, 2)= 7 AND ROUND(D, 2)= 16 AND ROUND(pcdc, 2)= 4 AND ROUND(pcdd, 2)= 114.3 AND ROUND(ET, 2)= 40 AND ROUND(DIA, 2)= 73.1

Скажите пожалуйста, на сколько такой запрос будет тормозить работу?

Отредактированно ebuilder (06.02.2011 13:33:00)

Неактивен

 

#10 06.02.2011 14:29:49

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Проблема с SELECT

А набор значений — фиксированный? Просто если есть два десятка стандартов,
то можно обойтись ENUM('73.1', '114.3', ...) — оно будет вести себя как строка,
но при этом храниться будет как число. Если нет — тогда, видимо, нужно будет
хранить, как строки sad

Как DOUBLE точно хранить не стоит, потому что если вдруг получите 114.2999 —
будет некрасиво smile

Неактивен

 

#11 06.02.2011 14:36:10

ebuilder
Участник
Зарегистрирован: 04.02.2011
Сообщений: 7

Re: Проблема с SELECT

набор значений — фиксированный, но ENUM - опять же непойдет, как сравнивать значения на < >  - больше меньше?

повторюсь),
что все-таки, склоняюсь к варианту:
SELECT * FROM `table` WHERE ROUND(w, 2)= 7 AND ROUND(D, 2)= 16 AND ROUND(pcdc, 2)= 4 AND ROUND(pcdd, 2)= 114.3 AND ROUND(ET, 2)= 40 AND ROUND(DIA, 2)= 73.1

Скажите пожалуйста, на сколько такой запрос будет тормозить работу?

Неактивен

 

#12 06.02.2011 15:35:22

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Проблема с SELECT

Ну, он никогда не будет использовать индексы. В остальном — нормальный.

Больше-меньше для ENUM вполне работают, надо только разместить размеры
в порядке увеличения.

Кстати, я совсем забыл — можно попробовать использовать DECIMAL — тот
же FLOAT, но без ошибок округления.

Неактивен

 

#13 06.02.2011 22:56:38

ebuilder
Участник
Зарегистрирован: 04.02.2011
Сообщений: 7

Re: Проблема с SELECT

Тип полей DECIMAL - работает, при значении DECIMAL(5,2) - 2 знака после запятой.

Дробные числа в базе стали вида 114.30, 73.10 ....
целые числа в базе стали вида 102.00, 57.00 ну и т.д.

SELECT * FROM `table` WHERE `pcdc`= 4 AND `pcdd`= 114.3 AND `ET`= 40 AND `DIA`= 73.1

выборка по равенству работает, индексы вроде тоже!

paulus большое спасибо!

Всем удачи!

Отредактированно ebuilder (06.02.2011 23:51:10)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson