Есть некоторая табличка с историей изменений какой-либо характеристики. Таких характеристик достаточно много и изменяются они достаточно часто. Для таблички я придумал структуру (в принципе, тривиально) Код (Text): id (int, key) value (float) time_point (datetime) Задача: в любой момент времени, надо получить набор актуальных (чаще всего последних) показаний характеристик. На ум пришло одно простое решение - сделать еще табличку, в которой и держать актуальные значения характеристик. В общем, неплохо работает. Но неразрешенной остается проблема получения характеристик актуальных на какой-нибудь прошлый период. Буду благодарен любой помощи
приведу для примера несколько записей Код (Text): id value time_point 1 10 01.01.2010 00-00-00 1 11 02.01.2010 00-00-00 1 16 02.01.2010 01-00-00 2 13 01.01.2010 00-00-00 2 15 01.01.2010 00-59-00 3 99 03.01.2010 00-00-00 ... Ну и надо выбрать все значения, актуальные на, допустим на 01.01.2010 00-59-00 Очевидно будет предположить, что это будет 2е записи Код (Text): id value 1. 1 10 2. 2 15 а на 01.02.2010 00-00-00 набор будет уже следующим: Код (Text): id value 1. 1 16 2. 2 15 3. 3 99
[sql]select id, value from table as t where value in (select value as val from table where id=t.id and time_point<$date order by time_point desc limit 1)[/sql]
Volt(220) спасибо =) то что доктор прописал. Моск мой не дошел до limit 1 вот, если для кого еще задача осталась непонятной, я поизвращался и изобразил её Где собственно, цвет полосочки характеризует значение величины. Еще раз спасибо
Опачки ( This version of MySQL doesn't yet support 'LIMIT _IN/ALL/ANY/SOME subquery' что же делать(( версия 5.4.3-beta-community
Simpliest а можно расширить) для приведенного примера полностью запрос. Я пока не сильно силен в мускуле
Simpliest Одно из двух: либо я совсем не понимаю действие конструкции MAX()< date. либо придется использовать join для вытаскивания value. ShamahN Как вариант можно перенести запрос из where в from и использовать join.
Simpliest Код (Text): SELECT `values`.id, `values`.account_id, `values`.value, `values`.time_point, `values`.user_id FROM `values` WHERE MAX(`values`.time_point) < '2010-04-02 14:48:25' GROUP BY `values`.account_id Пишет: неверное использование group function. Если убрать MAX то все работает, но не так как надо. Он не выбирает последнее значение
Ну парни, подумать чуток? агрегатные функции нельзя использовать в WHERE HAVING MAX(time_point) < date
да, один нюанс, при больших таблицах, выгоднее может оказаться таки JOIN или подзапрос поскольку HAVING вызывает filesort.
ну и до кучи: [sql]select value from table as t join (select id, max(time_point) as mtp from table where time_point<$date group by id) as actT on t.id=actT.id and t.time_point=actT.mtp[/sql]
Код (Text): mysql> select * from `values`; +----+------------+--------+---------------------+---------+ | id | account_id | value | time_point | user_id | +----+------------+--------+---------------------+---------+ | 1 | 1 | 10.000 | 2010-03-01 00:00:00 | admin | | 2 | 1 | 12.000 | 2010-04-01 14:00:00 | admin | | 3 | 1 | 15.000 | 2010-04-02 14:48:25 | admin | | 4 | 2 | 99.000 | 2010-04-01 15:14:02 | admin | +----+------------+--------+---------------------+---------+ запрос Код (Text): SELECT `values`.id, `values`.account_id, `values`.value, `values`.time_point, `values`.user_id FROM `values` GROUP BY `values`.account_id HAVING MAX(`values`.time_point) < '2010-04-02 14:48:25' выбирает только Код (Text): +----+------------+--------+---------------------+---------+ | id | account_id | value | time_point | user_id | +----+------------+--------+---------------------+---------+ | 4 | 2 | 99.000 | 2010-04-01 15:14:02 | admin | +----+------------+--------+---------------------+---------+ 1 row in set (0.00 sec) И это, парни))) давайте вы договоритесь между собой, и придем к какому-нить результату. Ибо все с чем я до сих пор общался - простые запросы с одним джоином)
Simpliest У меня есть подозрение что Код (Text): HAVING MAX(time_point) < date отсечет все id, для которых есть значения более поздние чем $date. UPD: Похоже подозрения подтвердились...
Не-не, либо мы все договариваемся, либо только мы (которые вы) придем. =))) Простой запрос с одним джоином. и из этого тоже можно сделать простой запрос с одним джоином. =) [sql]select id, value from table as t where value in (select value as val from table where id=t.id and time_point<$date order by time_point desc limit 1)[/sql]
Я имел ввиду - более чем один результат общения для меня это совсем немного лучше чем ниодного и вложенным запросом Все хорошо, но ругается, что нельзя в вложенных запросах юзать limit
Понятно. Это обычно происходит, когда человек не умеет думать самостоятельно. Проблема выбора его напрягает категорически.
Ну так вложенный запрос тоже простой. =)) Во-первых, я сказал что из этого тоже можно сделать. А во-вторых, он ругается не на все вложенные запросы, а только на некоторые.
Simpliest моя затупила простите сансей бью челом, - все работает... только как-то не правильно (( Код (Text): +----+------------+--------+---------------------+---------+ | id | account_id | value | time_point | user_id | +----+------------+--------+---------------------+---------+ | 1 | 1 | 10.000 | 2010-03-01 00:00:00 | admin | | 4 | 2 | 99.000 | 2010-04-01 15:14:02 | admin | +----+------------+--------+---------------------+---------+ а должно быть Код (Text): +----+--------+---------------------+ | id | value | time_point | +----+--------+---------------------+ | 3 | 15.000 | 2010-04-02 14:48:25 | | 4 | 99.000 | 2010-04-01 15:14:02 | +----+--------+---------------------+ Мы вибираем ближайшие к "2010-04-03 00:00:00" значения. данные - вот: Код (Text): +----+------------+--------+---------------------+---------+ | id | account_id | value | time_point | user_id | +----+------------+--------+---------------------+---------+ | 1 | 1 | 10.000 | 2010-03-01 00:00:00 | admin | | 2 | 1 | 12.000 | 2010-04-01 14:00:00 | admin | | 3 | 1 | 15.000 | 2010-04-02 14:48:25 | admin | | 4 | 2 | 99.000 | 2010-04-01 15:14:02 | admin | +----+------------+--------+---------------------+---------+
Вот пока что рабоспособный вариант, но какой-то он нетривиальный [sql] select `id`, `value`, `time_point` from `values` as t join (select account_id, max(`values`.time_point) as mtp from `values` where `values`.time_point<'2010-04-03 00:00:00' group by `account_id`) as actT on t.account_id=actT.account_id and t.time_point=actT.mtp[/sql] а если мне полученные данные по 'account_id' справа надо прилепить к какой-то таблице?)
Проверь на 2010-04-02 00:00:00 Возьми все в скобки и цепляй. =)) Грубо говоря что мы цепляем? Таблицы. А что нам возвращает запрос? Тоже таблицу. Так какая разница что цеплять запрос или таблицу?
Неправильно работает, почему-то( Но запрос: Отрабатывает идеально. Остановимся пока на нем (если конечно, не появится более красивого решения) Относительно этого запроса, как мне в список полей добавить еще 'account_id'. При добавлении ругается column 'account_id' in field list is ambiguous (ну и слово)