Конференция "Базы" » Запрос последней связи [MySQL]
 
  • Дмитрий С © (20.01.10 08:16) [0]
    Есть таблицы
    `auto` - столбцы: `id`, `number`  (автомобили)
    `client` - столбцы: `id`, `name`
    И связывающая их таблица заказов:
    `order` - столбцы `id`, `auto_id`, `client_id`, `create_time`

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

    Нужно получить список автомобилей и присоединить Имя последнего заказчика.

    Пока у меня несколько вариантов, которые меня не устраивают:
    1. Добавить в таблицу `auto` поле, где кешировать `client`.`id` последнего клиента. - не удобно поддерживать данное поле.
    2. Добавить в простой запрос из таблицы `auto` вложенный запрос - может быть очень медленно.

    А как сделать присоединением JOIN я пока не могу представить.

    Ваши предложения?

    БД: MySQL
  • Вариант (20.01.10 08:51) [1]
    Если правильно понял, то примерно так (выборка полей от фонаря, поставь сам нужные) - выбираться должны авто имеющие заказы и последний клиент сделавший заказ на  авто

    select a.number,c.name,o.id
    from auto a
    inner join orders o
    --(не нравится мне название order)
    ON o.auto_id=a.id
    inner join client c on c.id=o.client.id
    where o.create_time=(select MAX(o1.create_time) from orders o1 where o1.auto_id=a.id)



    PS: Запрос не проверял, написал навскидку.
  • Дмитрий С © (20.01.10 08:53) [2]

    > select MAX(o1.create_time) from orders o1 where o1.auto_id=a.
    > id

    Логически верно, а с точки зрения производительности?
    MySQL будет этот запрос выполнять для каждой строки?
  • Вариант (20.01.10 09:04) [3]

    > Дмитрий С ©   (20.01.10 08:53) [2]

    Сорри, по производительности не скажу. Не знаю MYSQL
    Но при наличии  индексов мне кажется тормозить не должно. План запроса покажет узкие места. Если запрос сильно тормозит, попробую подумать  еще...
  • turbouser © (20.01.10 09:10) [4]
    select a.number,c.name,o.id
    ,MAX(o.create_time)
    from auto a
    inner join orders o ON o.auto_id=a.id
    inner join client c on c.id=o.client.id
    group by a.number,c.name,o.id

  • Sergey13 © (20.01.10 09:42) [5]
    > [2] Дмитрий С ©   (20.01.10 08:53)
    > а с точки зрения производительности?

    А каковы объемы БД? А какие индексы есть? А попробовать наконец?
  • Дмитрий С © (20.01.10 09:44) [6]

    > turbouser ©   (20.01.10 09:10) [4]

    Попробовал - выдает не то, что нужно (даже количество записей другое)
    Можно прокомментировать?
  • Дмитрий С © (20.01.10 09:46) [7]

    > Sergey13 ©   (20.01.10 09:42) [5]
    >
    > А каковы объемы БД? А какие индексы есть? А попробовать
    > наконец?

    База проектируется пока, данных в ней почти нет пока.
    Индексы будут добавлены под запросы.
  • Sergey13 © (20.01.10 09:50) [8]
    > [7] Дмитрий С ©   (20.01.10 09:46)

    Ну а предполагаемый объем БД? А объем выборки?
    Что это - такси?
  • Дмитрий С © (20.01.10 10:04) [9]

    > Sergey13 ©   (20.01.10 09:50) [8]

    Программа для автосервиса.
    Около 2000 заказов в год.
    Клиентов в два раза меньше, автомобилей столько же.

    Запрос нужен для получения списка автомобилей (с фильтром), где указывается имя последнего клиента, что сдавал его в ремонт. Желательно по нему тоже фильтр сделать.
  • Дмитрий С © (20.01.10 10:06) [10]
    Запрос будет выполняться каждый раз, как будет редактироваться фильтр. Т.е. пользователь нажимает клавишу в поле фильтра - запрос выполнился - клиент увидел результат. Поэтому хочется, чтобы запрос выполнялся моментально.

    В запросе будет добавлено LIMIT 100
  • Кщд (20.01.10 10:17) [11]
    >Дмитрий С ©   (20.01.10 08:53) [2]
    >Логически верно, а с точки зрения производительности?
    логически неверно, т.к. надо выбирать максимальный ORDERS.ID (если автоинкрементное) соответствующий максимальному времени
    всё остальное - частные решения, существующие при ряде допущений
    выполняться будет быстро при наличии соответствующих индексов
  • Sergey13 © (20.01.10 10:29) [12]
    > [9] Дмитрий С ©   (20.01.10 10:04)
    > Около 2000 заказов в год.
    > Клиентов в два раза меньше, автомобилей столько же.

    Детские объемы. Не парься. В крайнем случае индекс по o1.create_time+o1.auto_id должен здорово помочь.

    Какой то странный у тебя автосервис. Для колхоза что ли? Много людей сдают много машин в разных сочетаниях. Странно как то.
    Я бы поставил во главу угла документ на проведение ремонта, по которому происходит оплата работы клиентом. Для обычного сервиса справочники авто и клиентов в принципе не обязательны (хоть и не помешают разумеется). ИМХО.
  • Кщд (20.01.10 10:30) [13]
    turbouser ©   (20.01.10 09:10) [4]
    нужно не время последнего заказа по каждому клиенту и автомобилю, а клиента, последним заказывавшего)
  • Кщд (20.01.10 10:33) [14]
    >Sergey13 ©   (20.01.10 10:29) [12]
    >В крайнем случае индекс по o1.create_time+o1.auto_id должен здорово помочь.
    т.е. два индекса: один - на orders.auto_id, другой - на orders.id
  • Дмитрий С © (20.01.10 11:01) [15]

    > Sergey13 ©   (20.01.10 10:29) [12]

    Я вот тоже думаю, убрать справочник клиентов. Добавить Имя к заказу и все. В случае чего можно будет сделать группировку по Имени.
  • Кщд (20.01.10 11:50) [16]
    >Дмитрий С ©   (20.01.10 11:01) [15]
    если нет разницы между Васисуалием Правдорубом пятнадцати лет от роду и однофамильцем Васисуалием восьмидесяти пяти лет, то и в справочнике нет необходимости, но тогда не ясно, зачем вообще надо показывать последнего клиента - ведь кто он конкретно неизвестно
  • Кщд (20.01.10 11:52) [17]
    к Кщд   (20.01.10 11:50) [16]
    денормализацию проводят для эффективности получения данных, но отнюдь не из-за лени, т.к. чревато
  • Sergey13 © (20.01.10 11:56) [18]
    > [14] Кщд   (20.01.10 10:33)

    Для конкретно этой выборки (из [1]) был бы полезен один составной индекс по auto_id+create_time. Теоретически подзапрос не должен вообще лезьть в таблицу - все данные есть в этом индексе. ИМХО.
  • Anatoly Podgoretsky © (20.01.10 11:59) [19]
    > Дмитрий С  (20.01.2010 08:16:00)  [0]

    Что такое Имя последнего заказчика, для меня это когда уже больше заказчиков не будет, квалификацие распугал.
 
Конференция "Базы" » Запрос последней связи [MySQL]
Есть новые Нет новых   [134435   +33][b:0][p:0.001]