SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 21.07.2010 16:58:33

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Помогите составить запрос

Есть задача. Таблица с данными о заездах.
Заезд содержит информацию о водителе, времени, и километраже.

Необходимо получить результат ввиде (по одному) лучшему результату на каждого водителя.
Лучшим результатом считается максимальное расстояние, пройдённое за самое меньшее время.

Набросал запрос:

SELECT DISTINCT `lid`, `km`, (finish-start) as tim FROM `cy2`.`es_arrival` WHERE `cid` = 1 ORDER BY `km` DESC, `tim` ASC LIMIT 0,10


Сама таблица:

CREATE TABLE IF NOT EXISTS `arrival` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cid` int(11) NOT NULL,
  `line` int(11) NOT NULL,
  `km` int(11) NOT NULL,
  `tid` int(11) NOT NULL,
  `lid` int(11) NOT NULL,
  `transport` int(11) NOT NULL,
  `period` int(11) NOT NULL,
  `date` date NOT NULL,
  `start` int(11) NOT NULL,
  `finish` int(11) NOT NULL,
  `temperature` int(11) NOT NULL,
  `pressure` int(11) NOT NULL,
  `wind` varchar(10) NOT NULL,
  `vlaga` int(11) NOT NULL,
  `prim` varchar(512) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8
 


Но конечно же DISTINCT срабатывает не только на lid, а надо фактически именно так.

Отредактированно binarius (21.07.2010 17:00:14)

Неактивен

 

#2 21.07.2010 17:32:00

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

Re: Помогите составить запрос

MAX(km / (finish - start)), lid GROUP BY lid?

Неактивен

 

#3 21.07.2010 17:56:10

devart
ISV
MySQL Enterprise Gold Partner
Откуда: www.devart.com
Зарегистрирован: 12.04.2010
Сообщений: 22

Re: Помогите составить запрос

может так?

SELECT
  a.lid,
  a.km,
  min(a.finish-a.start) as min_time
FROM es_arrival a
  INNER JOIN (select lid,max(km) as km_max from es_arrival where cid=1 group by lid) a_max
    ON a.lid=a_max.lid and a.km=a_max.km_max
WHERE
  a.cid=1
GROUP BY
  a.lid,a.km

Неактивен

 

#4 21.07.2010 19:04:51

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

2 проблемы возникли:

1. Пытаюсь добавить полей в выборку в начале запроса - добавляются поля из других записей почему то.
2. Как оптимизировать данный запрос, а то сплошной filesort.

Неактивен

 

#5 22.07.2010 00:52:36

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

Я может не понимаю очевидного? Но если сделать SELECT a.id, ... - запрос выбирает ID первый попавшийся... а не тот, что нужен. И так по всем полям. Первые попавшие под условие.

Сотню раз перепроверил, ID выдаёт как будто сортируя по ASC.

Совсем тупею?

Отредактированно binarius (22.07.2010 01:04:48)

Неактивен

 

#6 22.07.2010 03:39:01

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

Re: Помогите составить запрос

Если вы группируете не по всем полям, то Вы сами себе ставите палки в колеса.
Другие СУБД бы просто выдали ошибку, а MySQL пытается быть максимально
лояльным с пользователем. Но он правда не знает, какую строку выбрать при
группировке — выбирает любую.

Либо вы делаете несколько запросов для каждого пользователя с правильным
ORDER BY LIMIT 1, либо Вы достаете максимальные значения и пользователей,
а остальные данные получаете присоединением (JOIN) основной таблицы по
вот этим коротким группировочным данным.

И оптимизировать не получится, т.к. Вы делаете MAX(a - b), что не позволит
использовать индекс никогда. Подсказка: если хранить не «a и b», а «а и b-a»,
то информацию Вы не теряете, а вот на этом запросе сможете немного выиграть.

Неактивен

 

#7 22.07.2010 13:48:17

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

Хм насчет оптимизации понял. В принципе эти запросы редки и сразу в кеш положить уже готовую страницу не проблема, ибо она обновляется минимум раз в сутки.

А насчет группировки - я пытался туда добавлять поля, появлялись лишние строки. Не понял почему. Начинали присутствовать строки, которые нужны и побочные... или тут имеет разницу порядок группировки, также как и в ORDER BY?

Отредактированно binarius (22.07.2010 13:51:38)

Неактивен

 

#8 22.07.2010 13:58:21

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

Поигрался с группировкой, порядком полей. Делал все возможные комбинации с простым добавлением просто ещё выборки ID записи, однако к каждой строке вылезает одна побочная.

Может дамп в студию маленький выкатить?

Неактивен

 

#9 22.07.2010 14:10:03

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

Re: Помогите составить запрос

Если Вы сгруппируете по всем полям, то получите DISTINCT, от которого
Вы пытаетесь уйти smile Группировать надо по тем полям, которые должны
быть по смыслу. По остальным полям нужно (SHOULD в понимании RFC)
писать групповые функции или смириться с тем, что там будет возвращено
произвольное значение из диапазона.

Неактивен

 

#10 22.07.2010 14:36:19

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

Блин вот тробл. Ну мне надо всего лишь ID вытащить помимо того, что есть. А по ID я уже другими запросами всё возьму... Ладно даже фиг ты с ними с побочными данными, может тогда проще озаботиться фильтрацией не нужного? Если да, то тогда вопрос, что лучше - использовать средства MySQL или PHP.

Неактивен

 

#11 22.07.2010 14:49:42

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

Re: Помогите составить запрос

Определитесь, что есть лучшее расстояние. Если то, что Вы написали, то надо
искать строку с MAX( km / ( stop - start )). Вы же предпочитаете вариант
максимального расстояния (а при равных расстояниях — минимального времени).

После этого Вы сможете составить запрос, который будет отвечать на вопрос
«найди всех гонщиков, и их максимальную характеристику». После этого Вы
сможете составить запрос, который будет отвечать на вопрос «Найди всех гонщиков,
у которых вот такая максимальная характеристика».

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

Неактивен

 

#12 22.07.2010 15:09:45

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

Попробывал:

SELECT MAX( km / ( finish -
START ) ) as value, lid, id
FROM `es_arrival`
WHERE `cid` =1
GROUP BY lid


Тут я так понимаю и должно быть бредовое значение поля value. Ну оно меня и не шибко интересует, однако выбирает не те строки. Он точнее (как наблюдаю) выводит максимальное время, за минимальное расстояние. То есть наоборот, а как перевернуть-то? ORDER BY DESC? Просто насколько я понимаю вложенные MIN(MAX( невозможны.

Неактивен

 

#13 22.07.2010 15:27:04

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

SELECT (MAX( km ) / MIN(finish-start)) AS value, lid, id FROM `es_arrival` WHERE `cid` =1 GROUP BY lid

Даёт такой же эффект что и предыдущий запрос. Тогда я вообще не понимаю.

Неактивен

 

#14 23.07.2010 00:20:19

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

Пошел по пути денормализации, добавил поле time, которое содержит finish-start, может тут легче что-то придумать?

Неактивен

 

#15 23.07.2010 00:34:51

binarius
Участник
Зарегистрирован: 07.04.2010
Сообщений: 14

Re: Помогите составить запрос

Ух сделал я это драконьим ORDER BY LIMIT 0,1 с двумя доп.запросами. Зато работает.

Тема исчерпана, всем спасибо!

Неактивен

 

Board footer

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