SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 07.08.2016 16:13:21

Дмитрий79
Участник
Зарегистрирован: 07.08.2016
Сообщений: 15

Как сделать правильный запрос

Добрый день! Есть таблица(см. рисунок). Скажите, пожалуйста, как правильно сформировать запрос, чтобы для каждого CLAIM_ID правильно выбирался STORAGE_ID?
Запрос SELECT * , MIN( DISTANCE ) FROM  `table` GROUP BY  `CLAIM_ID` выдаёт неверный результат.

Как видно из рисунка, для каждого CLAIM_ID STORAGE_ID равен 58 - что неверно.

Правильно:
для CLAIM_ID  = 1, STORAGE_ID = 43366;
для CLAIM_ID  = 1, STORAGE_ID = 35859;

Как написать правильный запрос?

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

Заранее благодарен!


Прикрепленные файлы:
Attachment Icon table.png, Размер: 504,027 байт, Скачано: 341

Неактивен

 

#2 07.08.2016 16:36:48

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2420

Re: Как сделать правильный запрос

Добрый день!
Не вполне понятно, как именно нужно выбирать STORAGE_ID для каждого CLAIM_ID?
И сколько именно нужно выбрать STORAGE_ID для каждого CLAIM_ID? Один или два или сколько? (А главное, почему один, два, или три).

Товарно-рыночные отношения на форуме sqlinfo в виде обмена хранимками -  наверное первый случай в истории форума smile!
Глянуть, безусловно, интересно на такую хранимку.
А какой Датум? WGS84?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 07.08.2016 17:00:23

Дмитрий79
Участник
Зарегистрирован: 07.08.2016
Сообщений: 15

Re: Как сделать правильный запрос

Есть один CLAIM_ID(заявка) и есть сотни STORAGE_ID(склады). Нужно найти ближайший(соответственно, единственный) склад к каждой заявке(в данном случае их две) - вот такая задача.

Вот хранимка
DELIMITER //
CREATE FUNCTION DISTANCE(lat1 DOUBLE, lng1 DOUBLE, lat2 DOUBLE, lng2 DOUBLE)
RETURNS DOUBLE
BEGIN
    DECLARE deltaLng, cosLat1, cosLat2, sinLat1, sinLat2, cosDeltaLng, sinDeltaLng, y1, y2, x1, x2, x, y, R DOUBLE;
    SET R=6372795;
    SET lat1 = lat1*0.017453292519943295769;
    SET lng1 = lng1*0.017453292519943295769;
    SET lat2 = lat2*0.017453292519943295769;
    SET lng2 = lng2*0.017453292519943295769;
    SET deltaLng = ABS(lng2-lng1);
    SET cosLat1 = COS(lat1);
    SET cosLat2 = COS(lat2);
    SET sinLat1 = SIN(lat1);
    SET sinLat2 = SIN(lat2);
    SET cosDeltaLng = COS(deltaLng);
    SET    sinDeltaLng = SIN(deltaLng);
    SET y1 = cosLat2*sinDeltaLng;
    SET y2 = cosLat1*sinLat2-sinLat1*cosLat2*cosDeltaLng;
    SET y = SQRT(y1*y1+y2*y2);
    SET x1 = sinLat1*sinLat2;
    SET x2 = cosLat1*cosLat2*cosDeltaLng;
    SET x = x1 + x2;
    RETURN ATAN2(y,x)*R;
END //

Отредактированно Дмитрий79 (07.08.2016 17:03:16)

Неактивен

 

#4 07.08.2016 17:01:16

Дмитрий79
Участник
Зарегистрирован: 07.08.2016
Сообщений: 15

Re: Как сделать правильный запрос

CREATE TABLE IF NOT EXISTS `distances_268` (
  `CLAIM_ID` int(18) unsigned NOT NULL DEFAULT '0',
  `LAT1` double(20,12) DEFAULT '0.000000000000',
  `LNG1` double(20,12) DEFAULT '0.000000000000',
  `LAT2` double DEFAULT NULL,
  `LNG2` double DEFAULT NULL,
  `STORAGE_ID` int(11) unsigned NOT NULL DEFAULT '0',
  `DISTANCE` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `distances_268` (`CLAIM_ID`, `LAT1`, `LNG1`, `LAT2`, `LNG2`, `STORAGE_ID`, `DISTANCE`) VALUES
(1, 60.976641000000, 32.955478000000, 66.5281, 66.590989, 58, 1739997.10851877),
(1, 60.976641000000, 32.955478000000, 66.60495, 66.615315, 59, 1741792.47486379),
(1, 60.976641000000, 32.955478000000, 66.527108, 66.63816, 60, 1742070.80418416),
(1, 60.976641000000, 32.955478000000, 66.525077, 66.58745, 61, 1739813.14727011),
(1, 60.976641000000, 32.955478000000, 66.530715, 66.613851, 62, 1741030.37968224),
(1, 60.976641000000, 32.955478000000, 66.535019, 66.589067, 63, 1739975.89509031),
(1, 60.976641000000, 32.955478000000, 66.526771, 66.589157, 64, 1739904.03823327),
(1, 60.976641000000, 32.955478000000, 66.530715, 66.613851, 65, 1741030.37968224),
(1, 60.976641000000, 32.955478000000, 66.527108, 66.63816, 66, 1742070.80418416),
(1, 60.976641000000, 32.955478000000, 56.252627, 38.115437, 35859, 604083.105780824),
(1, 60.976641000000, 32.955478000000, 58.307715, 32.490222, 43366, 298002.497726852),
(2, 56.718187000000, 38.828160000000, 66.5281, 66.590989, 58, 1803606.473075),
(2, 56.718187000000, 38.828160000000, 66.60495, 66.615315, 59, 1808046.25611387),
(2, 56.718187000000, 38.828160000000, 66.527108, 66.63816, 60, 1805475.54941968),
(2, 56.718187000000, 38.828160000000, 66.525077, 66.58745, 61, 1803327.58157761),
(2, 56.718187000000, 38.828160000000, 66.530715, 66.613851, 62, 1804650.6583059),
(2, 56.718187000000, 38.828160000000, 66.535019, 66.589067, 63, 1803838.55600679),
(2, 56.718187000000, 38.828160000000, 66.526771, 66.589157, 64, 1803472.66485256),
(2, 56.718187000000, 38.828160000000, 66.530715, 66.613851, 65, 1804650.6583059),
(2, 56.718187000000, 38.828160000000, 66.527108, 66.63816, 66, 1805475.54941968),
(2, 56.718187000000, 38.828160000000, 56.252627, 38.115437, 35859, 67802.7395046658),
(2, 56.718187000000, 38.828160000000, 58.307715, 32.490222, 43366, 417658.344099849)

Неактивен

 

#5 07.08.2016 18:58:43

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5833

Re: Как сделать правильный запрос

т.е. для каждой заявки нужно выбрать строку с минимальным значением DISTANCE?
Тогда ответ - тут

что если есть 2 ближайших склада для заявки?

Неактивен

 

#6 07.08.2016 21:51:55

Дмитрий79
Участник
Зарегистрирован: 07.08.2016
Сообщений: 15

Re: Как сделать правильный запрос

Большое спасибо за ссылку!

Как видим, значение поля post взято не из той строки, которая соответствует max(`time`). А если результат правильный, то это не более чем случайность. написал:

Василий Лукьянчиков

Как раз мой случай.

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

Получается, что такая тривиальная, казалось бы задача, на поверку оказывается несколько сложной.

Отредактированно Дмитрий79 (07.08.2016 21:53:00)

Неактивен

 

Board footer

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