Условие для GROUP BY

Тема в разделе "Базы данных", создана пользователем venetu, 14 апр 2010.

Статус темы:
Закрыта.
Модераторы: latteo
  1. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    735
    Симпатии:
    261
    Есть таблица
    id, products_id, price, date

    В которой записаны цены на продукты. У каждого продукта - несколько цен, в зависимости от даты. Актуальна всегда последняя цена (с самым большим date), прошлые хранятся для истории. Цены меняются далеко не ежедневно, т.е. не для каждой даты есть соотв. запись в таблице.

    Задача: селектнуть самые новые цены.

    причем так, чтоб потом в этот запрос еще можно было вставить WHERE `date` < '2009-01-01', т.е. "последние(актуальные) цены по состоянию на такое-то число"


    Я подозреваю, что тут надо копать в сторону HAVING, но
    SELECT products_id, price, date FROM table GROUP BY products_id HAVING date=MAX(date) нужного результата не дает. Наверное, MAX() считается по всей таблице, а не для каждого products_id отдельно.

    Короче в более общем случае можно сформулировать так - как сказать мускулу, чтоб при GROUP BY он из группы оставил конкретный какой-то ряд (в моем случае - запись с максимальным date).
     
  2. polyetilen

    polyetilen Заблокирован

    Регистр.:
    10 авг 2006
    Сообщения:
    814
    Симпатии:
    474
    один из вариантов с субзапросами, один запрос делает список продуктов и их максимальной даты, а другой запрос составляет весь список по первому сверяя по дате и ид продукта
    Код:
    SELECT t1.* FROM product t1, 
    (
        SELECT products_id, MAX(date) date
        FROM product
        ##или с условием
        ##WHERE date < '2010-04-14'
        GROUP BY products_id 
        ORDER BY date
    ) filter
    
    WHERE t1.products_id=filter.products_id AND t1.date=filter.date
    ;
    
     
    venetu нравится это.
  3. Budulayj

    Budulayj Постоялец

    Регистр.:
    17 июн 2008
    Сообщения:
    52
    Симпатии:
    8
    Можно так еще:
    SELECT
    t.date,
    t.products_id,
    t.price
    FROM test t
    WHERE t.date=(SELECT max(t1.date) FROM test t1 WHERE t1.products_id = t.products_id /*здесь можно вставить условие на дату*/)

    По-моему, с Group by не получится сделать задуманное.
     
  4. Abliganto

    Abliganto Постоялец

    Регистр.:
    30 ноя 2009
    Сообщения:
    111
    Симпатии:
    46
    Это старая больная проблема MySQL, у неё даже есть название (не вспомню сейчас), было много обсуждений на mysql.com. Над ней смеются все крутые спецы по БД (Oracle, MS-SQL, Postgre)

    На самом деле в нормальных SQL нельзя вытащить из запроса с GROUP BY значения полученые не из групповых ф-ций (MAX, MIN, AVG, GROUP_CONCAT и т.д.) либо полей не участвующих в перечислении GROUP BY

    В одну дату может выйти 2 значения

    Я раньше использовал вариант polyetilen, только ORDER BY date DESC

    Теоретически mysql не гарантирует что в этом запросе будет возвращено первое значение, но на деле оно работает :)

    Но потом я вообще отказался от таких запросов в пользу реструктуризации БД и создания спец. выборок последних продуктов.
     
  5. Budulayj

    Budulayj Постоялец

    Регистр.:
    17 июн 2008
    Сообщения:
    52
    Симпатии:
    8
    Судя по информации от ТС ("Актуальна всегда последняя цена (с самым большим date)"), то не может.
     
  6. Abliganto

    Abliganto Постоялец

    Регистр.:
    30 ноя 2009
    Сообщения:
    111
    Симпатии:
    46
    Да, верно, если там тип datetime, я что-то подумал, что date :)

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

    Я обычно стараюсь использовать простые запросы в подобных случаях (да и ОРМ навязывает ;)). 1м вытаскиваю IDшки, 2м достаю уже данные.
     
Статус темы:
Закрыта.