Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [MySQL] Выборка последних записей в GROUP BY 
:(
    Опции темы
s1lver
  Дата 3.2.2016, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 580
Регистрация: 14.12.2007
Где: Россия

Репутация: нет
Всего: нет



Доброго времени суток!

Необходимо выбрать последние записи из таблицы для каждого идентификатора(количество идентификаторов может различаться каждый раз). 
Код

[1, 2, 3]


Сделал используя UNION так:

Код

(SELECT `avg_balance` FROM `product` WHERE nomenclature = 1 ORDER BY `date` DESC LIMIT 1)
UNION
(SELECT `avg_balance` FROM `product` WHERE nomenclature = 2 ORDER BY `date` DESC LIMIT 1)
UNION
(SELECT `avg_balance` FROM `product` WHERE nomenclature = 3 ORDER BY `date` DESC LIMIT 1)


Запрос возвращает правильные данные. Но, хотелось бы, используя IN, как-то так:

Код

SELECT `avg_balance`
FROM `product` 
WHERE nomenclature IN (1,2,3)
GROUP BY `nomenclature`
ORDER BY `date` DESC


В этом случае, тоже работает, но только, естественно, возвращает первые записи. 

Подскажите, пожалуйста, как можно поправить в этом случае?


--------------------
Я собрался жить вечно - пока все идет нормально!
PM MAIL ICQ   Вверх
Akina
Дата 3.2.2016, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20570
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 453



См. тут.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
tzirechnoy
  Дата 3.2.2016, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



(в приличных серверах второй код не заработает, кстати, поскольку поле в ORDER, да и поле в SELECT несгруппированы в запросе с группировкой)

Код
SELECT avg_balance, nomenclature 
  FROM product p1 
  WHERE nomenclature IN (1,2,3) 
    AND date=(SELECT max(date) 
                 FROM product p2 
                 WHERE p2.nomenclature=p1.nomenclature)


Есть, правда, такая деталь, что если дата неуникальна, то выдаст всё за последнюю дату, но это не всегда плохо по факту. А если плохо -- то можно ещё добавить фильтр по любому уникальному ключу: 
Код

  AND id=(SELECT max(id)
            FROM product p2
            WHERE p2.nomenclature=p1.nomenclature
                  AND p2.date=p1.date)


И вторая деталь -- часто в серверах проблема с тем, чтобы понять что оператор max требует одной выборки по ключу (и вообще с оптимизацыей групповых операторов), потому для скорости можэт иметь смысл переписать SELECT max(date) FROM ... WHERE на ваш SELECT date FROM ... WHERE ... ORDER BY date DESC LIMIT 1.
PM MAIL   Вверх
s1lver
Дата 3.2.2016, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 580
Регистрация: 14.12.2007
Где: Россия

Репутация: нет
Всего: нет



Вот, еще вариант получился

Код

SELECT `s`.avg_balance
FROM (
    SELECT MAX(`id`) AS `max_id`
    FROM `product`
    GROUP BY `nomenclature`
    ORDER BY `date` DESC
 ) AS `a`
 LEFT JOIN `product` AS `s` ON `a`.`max_id` = `s`.`id`


Как бы, даже, возвращает правильные данные  smile

Добавлено @ 12:33
Akina
tzirechnoy

Теперь еще "хуже". Есть три варианта, которые возвращают нужные данные, проблема какой использовать.  smile 

Это сообщение отредактировал(а) s1lver - 3.2.2016, 12:37


--------------------
Я собрался жить вечно - пока все идет нормально!
PM MAIL ICQ   Вверх
Akina
Дата 3.2.2016, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20570
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 453



Цитата(s1lver @  3.2.2016,  13:29 Найти цитируемый пост)
Есть три варианта, которые возвращают нужные данные

Внимательно прочитайте по ссылке варианты постановки задачи и проверьте, ту ли задачу решаете в каждом из вариантов.

Цитата(s1lver @  3.2.2016,  13:29 Найти цитируемый пост)
проблема какой использовать.

А вот это уже зависит от конкретной системы - начиная с наполнения таблиц и кончая аппаратной конфигой. 


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
s1lver
Дата 3.2.2016, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 580
Регистрация: 14.12.2007
Где: Россия

Репутация: нет
Всего: нет



Цитата

Есть, правда, такая деталь, что если дата неуникальна, то выдаст всё за последнюю дату, но это не всегда плохо по факту. А если плохо -- то можно ещё добавить фильтр по любому уникальному ключу


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

SELECT `avg_balance`
FROM `product` p1
WHERE (`nomenclature` IN ('1', '2', '3')) 
AND (`date` = (
    SELECT MAX(`date`) 
    FROM `product` p2 
    WHERE p2.nomenclature = p1.nomenclature
    AND (p2.date >= (UNIX_TIMESTAMP(CURDATE()-1) - 24*60*60)) 
    AND (p2.date < UNIX_TIMESTAMP(CURDATE()))
    ) 
)


На первый взгляд, возвращаемые данные правильные 
Цитата

Внимательно прочитайте по ссылке варианты постановки задачи и проверьте, ту ли задачу решаете в каждом из вариантов.


Судя по всему, все правильно. smile 

Это сообщение отредактировал(а) s1lver - 3.2.2016, 13:16


--------------------
Я собрался жить вечно - пока все идет нормально!
PM MAIL ICQ   Вверх
tzirechnoy
Дата 3.2.2016, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



Цитата
Как бы, даже, возвращает правильные данные 


Как бы нет. То есть он возвращает имено данные для самого большого id, а не самой большой даты. А ORDER BY -- вообще не работает, и правильный сервер об этом бы сказал.

Переделать на дату -- можно. Разница с подзапросом в WHERE будет в том, что в одном случае для поиска максимальных дат оптимизатор скорее всего один раз пройдёт по product, получив список дат по номенклатурам, а в другом -- столько раз, сколько нужно номенклатур, пройдёт по ключу, свзязанному с номенклатурой. В общем, по скорости можэт быть лучшэ и так и так -- в зависимости от селективности номенклатуры и количества их в одном запросе. Правда, подзапрос в WHERE можно переделать на ORDER BY ... LIMIT 1, и заставить использовать индэкс, а во FROM по-моему это тяжэловато.


PM MAIL   Вверх
Akina
Дата 3.2.2016, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20570
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 453



Цитата(s1lver)

Код

p2.date >= (UNIX_TIMESTAMP(CURDATE()-1) - 24*60*60)


Ахринеть... а почему не просто просто 
Код

p2.date >= CURDATE() - INTERVAL 1 DAY

?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.1301 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.