![]() |
|
Модераторы: skyboy |
![]()
|
|
| Kurt |
|
||||||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Вспомнил, как ходил в прошлом году на собеседование. Мне тогда дали такую задачку:
есть таблица:
Это таблица изменений цен на валюту (пусть, для простоты, это цена покупки). Например, есть такие данные:
Задача: получить актуальную стоимость каждой валюты в формате "дата_последнего_изменения, название_валюты, цена" То есть в данном примере ответ:
Задачу предлагалось решить на MSSQL2000 и я как-то вывертелся через вложенный запрос, что явно очень не понравилось моим "экзаменаторам". Прошли годы. На то место я не устроился, о чем, правда, не сожалею. Однако, вот теперь задумался, как решить такую задачу на MySQL 3.23 - то есть до появления вложенных запросов? -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
||||||
|
|||||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Это по последней дате? А разве нельзя сгруппировать по типу валюты, отсортировав по дате и снять первую строку с каждой группы? -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Kurt |
|
|||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Одним запросом? (меня просили одним)
А ну, покажи, что-то я наверное совсем туплю.. -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Да я сам туплю... Пока порешал созданием временной таблицы... Но пятой точкой чую что можно одним запросом и эффективно... -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Secandr |
|
||||
|
Связист ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4043 Регистрация: 3.8.2003 Где: Russia, Volgograd Репутация: 6 Всего: 39 |
Может так:
Или ещё проще:
И разобрать средствами php, допустим. |
||||
|
|||||
| Kurt |
|
||||||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Secandr Количество валют нежестко задано. Их может быть две (как у меня в примере), а момет быть 50. Поэтому этот запрос не будет решением.
Согласен. Но меня просили получить результат одним запросом. Без привлечения сторонних технологий типа PHP, ASP etc. -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
||||||
|
|||||||
| Secandr |
|
|||
|
Связист ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4043 Регистрация: 3.8.2003 Где: Russia, Volgograd Репутация: 6 Всего: 39 |
надо попробовать, есть пара дурных идей...
|
|||
|
||||
| Zipo |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 151 Регистрация: 4.11.2003 Репутация: нет Всего: 0 |
Тут вся трудность в дефолтной сортировке по дате. Физически данные будут храниться отсорированные по дате нарастающе (ASC). Т.к. заполняя таблицу мы каждый раз вводим дату большую чем предыдущая.
В MySQL данные храняться так же как и в MSSQL таблицах при отсутствии кластерного индекса. Я не встречал создание индексов с указанием направления сортировки. В MySQL этого вроде и нету. Задача решается таким запросом:
Т.е. мы сортируем таблицу в нужном нам направлении по дате. Потом группируем по валюте и в итоге получим, то, что хотели. Если кто знает как создать индекс с указанием направления сортировки (что бы данные физически хранились отсортированные по дате на DESC), то от вложеного запроса можно избавиться. |
|||
|
||||
| Kurt |
|
|||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Zipo
К сожалению, задача таким запросом не решится. Более того, он даже не будет выполнен, т.к. синтаксически не верен. У меня нет под рукой MySQL 4.1 (чтоб вложенные запросы работали), но я проверил свою догадку на MSSQL2000. Во-первых, MSSQL не разрешает сортировку в подзапросе. Если не ошибаюсь, MySQL это также запрещает. А во-вторых, даже если не обращать внимание на сортировку, то:
То есть столбцы таблицы должны быть упомянуты либо в агрегатной ф-ции, либо в group by. Уверен, это же правило распространяется и на другие СУБД. P.S. В тестовой таблице, что мне предлагали, даты были перемешаны в случайном порядке. То есть не обязательно нижняя дата для каждой валюты больше верхней даты. Это просто я в примере так написал. -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
|||
|
||||
| Zipo |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 151 Регистрация: 4.11.2003 Репутация: нет Всего: 0 |
Я не писал если бы не проверил. У меня MySQL 4.1.7
Запрос корректно отрабатывает у меня. Знаю, что MySQL не позволяет использовать LIMIT во вложенном запросе. О сортировках подобного не слышал.
Это скорее всего тоже ограничение MySQL 3.23 MySQL при группировке по определенным столбцам дает значения колонкам которые не вошли в группировку из первой записи которую он нашел эквивалентной группе. Группа у нас это валюта. Остальные поля получают значение из первой найденной строки для этой группы. Поэтому я и обратил Ваше внимание на сортировку. В MSSQL сортировку использовать нельзя если во вложенном запросе нету TOP. С группировкой в MSSQL так непроходит. |
|||
|
||||
| Zipo |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 151 Регистрация: 4.11.2003 Репутация: нет Всего: 0 |
Для MSSQL оптимальным скорее всего будет процедура
Это конечно при условии, что обновление позиции происходит для всех валют. Т.е. не может быть обновление одной вылюты а потом другой через неделю. |
|||
|
||||
| S.A.P. |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2664 Регистрация: 11.6.2004 Репутация: нет Всего: 71 |
так пойдет? Работает только в том случае, если курс валют не задан на перед... |
|||
|
||||
| Kurt |
|
||||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Zipo
Хм.. Ваше решение в MSSQL через процедуру очень интересно. Возьму на вооружение.
сильно снижает практическое применение такого решения. А вот с MySQL. Как бы добиться правильного результата на MySQL 3.23. Не знаю почему, но почти во всех (даже самых современных) дистрибутивах Linux я встречаю именно 3.23, кроме того, на многих хостингах также используется эта база. Ради спортивного интереса хотелось бы все-таки решить эту задачу для MySQL 3.23. Perchilla Не. Не пойдет. Вот, смотри, что возвращает твой запрос:
Согласись, цены явно не те. З.Ы. Вот такие вот задачки дают у нас в деревне на собеседованиях. -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
||||
|
|||||
| Ignat |
|
||||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Не уверен, что они сами знают на нее ответ. Вполне вероятно, что это попытка решить задачку за счет соискателя. Я тоже подумаю над этой задачкой. У меня сегодня такая-же выползла, только там четыре строки, а делать четыре запроса ломает.. Добавлено @ 22:10 Что-то мне сдается будет вроде этого, но не проверял.
-------------------- Теперь при чем :P |
||||
|
|||||
| Kurt |
|
||||||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Не, не то. Смотри, что получается:
-------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
||||||
|
|||||||
| Akina |
|
|||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 106 Всего: 454 |
WHERE vdate <= CURDATE() -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Kurt, не тот я порядок сортировки влепил, виноват.
-------------------- Теперь при чем :P |
|||
|
||||
| Zipo |
|
||||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 151 Регистрация: 4.11.2003 Репутация: нет Всего: 0 |
Это логически неправильное решение. Нет смысла делать сортировку после группировки. Добавлено @ 10:53
Самый главный фактор, что бы не происходило обновление одной валюты чаще чем других. Именно в этом случае процедура отработает неправильно. В принципе если ставить обновление валют на автомате к примеру с сайта нац. банка, то такая ситуация не произойдет. Не встречал потребностей в ручном обновлении. |
||||||||
|
|||||||||
| Ignat |
|
||||||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Да ну? Вопрос в том, что будет отправлено клиенту. Вначале выбираются ряды, группируются (т.е. меняется порядок, а не удаление дубликатов значений столбца), затем в пределах группировки производится сортировка, а затем уже DISTINCT. для сомневающихся:
источник Zipo, прежде чем назвать чье-то решение неправильным, следует быть уверенным в своей правоте. Добавлено @ 12:05
для MySQL это выглядит WHERE vdate <= NOW() Это сообщение отредактировал(а) Ignat - 5.9.2005, 12:07 -------------------- Теперь при чем :P |
||||||
|
|||||||
| Akina |
|
|||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 106 Всего: 454 |
не понял... время-то вроде как не нужно... -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Akina, хм... да диалект здесь не при делах.
насколько помню, сравнение в этом случае корректно (date vs datetime). Но по смыслу котировок, могу предположить, что они обновляются куда чаще, чем раз в день -------------------- Теперь при чем :P |
|||
|
||||
| Akina |
|
|||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 106 Всего: 454 |
Ignat
Я исходил из приведенных в инит-посте данных - там нет времени. -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
| Bikutoru |
|
||||||||
|
Увлекающийся ![]() ![]() Профиль Группа: Участник Сообщений: 522 Регистрация: 24.5.2005 Где: Москва Репутация: 1 Всего: 22 |
Ignat, практика показывает, что ты не совсем прав. Проверял на MySQL 3.23.52-log на данных Kurt'a
Запрос 1.
Результат: 02.01.2000 USD 20,5 04.01.2000 EURO 21,5 Запрос №2.
Результат: 04.01.2000 EURO 21,5 02.01.2000 USD 20,5 Запрос №3.
Результат: 04.01.2000 EURO 21,5 02.01.2000 USD 20,5 (меняющиеся друг с другом местами) Так что
остаётся открытым. -------------------- Человек, словно в зеркале мир — многолик, Он ничтожен — и он же безмерно велик! Омар Хайям |
||||||||
|
|||||||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Bikutoru, спасибо.
Zipo, прошу прощения за резкость. Проверил. Вариант, который у меня заработал:
Но не нравится мне он. Очевидно, если поле времени будет заполнено не возрастанием, то результатом будет произвольный порядок. Проверил на 120 записях с группировкой по ~30 значениям. -------------------- Теперь при чем :P |
|||
|
||||
| Zipo |
|
||||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 151 Регистрация: 4.11.2003 Репутация: нет Всего: 0 |
Ignat:
Все дело в том, что для произведения операции группировки БД необходимо выполнить сортировку по указаному полю для группировки и только после этого БД удаляет дубликаты. Именно по этому в группировке можно указывать направление сортировки (ASC/DESC). Это дает приимущество только в случае если в качестве результата нужно получить сортированные список по полю группировки (т.е. что бы не производить еще 1 операцию сортировки методом ORDER BY). Вы немного заблудились в реализации алгоритмов БД MySQL.
Именно об этом говориться в этой цитате.
1. Отбираются ряды соотв. условию 2. Сортируются по полям группировки (в указаном направлении ASC/DESC) 3. Удаление дубликатов (DISTINCT) В приделах групп сортировки не происходит. Все операции происходят в том порядке в котором они написаны в sql выражении. То, что Вы хотите логически неправильно. Этого хотеть не нужно. Абсолютно все БД из соображения скорости будут поступать по указаному мной плану. Дальше, можете меня хоть застрелить, но я повторюсь: Это логически неправильное решение. Нет смысла делать сортировку после группировки. Теперь объясню почему: ORDER BY всегда будет и выполнялся только после окончательного выполнения GROUP BY (т.е. все дубликаты уже удалены). Делать сортировку после группировки мне видится логичным только в 1 случае, это в версиях MySQL > 4.0. По полям которые не вошли в группу GROUP BY. Почитайте в этой теме я объяснял логигу группировки MySQL > 4.0. Но это действует только в указаной версии БД, MSSQL уже ругается и выдает ошибку. Но метод реализации группировки в этой БД дает приимущестава, без потери скорости. Добавлено @ 15:21
Этот вариант тоже логически неверен. И работать не будет. Прочитайте мои первые посты в этой теме. Вам должно стать ясно почему так происходит. |
||||||||
|
|||||||||
| Ignat |
|
||||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
2Kurt, перерыл документацию. Судя по всему, то что оттебя хотели:
Но в MySQL это отпадает. Обидно. Добавлено @ 15:30
Не сомневаюсь. -------------------- Теперь при чем :P |
||||
|
|||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
-------------------- Теперь при чем :P |
|||
|
||||
| Kurt |
|
||||||||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Нет. MSSQL ругается:
ему второй group by не нравится.
Да. Времени там не было. Хотя сейчас понимаю, что по-хорошему должно быть. Но давайте все так же не учитывать время - чтоб совпадало с задачкой на собеседовании. -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
||||||||
|
|||||||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Kurt, посмотри последний линк. Там хорошо раписано.
-------------------- Теперь при чем :P |
|||
|
||||
| dm9 |
|
|||
![]() Дмитрий Копытин ![]() ![]() ![]() ![]() Профиль Группа: Vingrad developer Сообщений: 3876 Регистрация: 22.7.2002 Где: Москва Репутация: нет Всего: 137 |
Или я чего-то не понял, или это трюк "MAX-CONCAT".
Данной задаче посвящена целая страница в мане по MySQL. Более быстрого решения в один запрос, как утверждается в мане, не существует. http://www.mysql.ru/docs/man/example-Maxim...-group-row.html Igant, ты эту ссылку и привёл. Прошу прощения. Надо внимательнее читать. Но пост удалять не буду, поскольку он содержит готовый запрос... Это сообщение отредактировал(а) dm9 - 6.9.2005, 10:12 |
|||
|
||||
| Kurt |
|
|||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Ох.. вот он какой - северный олень..
Все понял, всем спасибо. Из всего этого топика я вынес главную мысль - если мне когда-нибудь понадобится хранить историю валют, я буду придумывать какую-нибудь другую структуру. -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
|||
|
||||
| Kurt |
|
|||
|
Увлеченный ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1662 Регистрация: 22.8.2003 Где: Краснодар Репутация: 1 Всего: 36 |
Недавно мой знакомый нашел простое и очень логичное решение этой задачи для PostgreSQL:
Я удивлен, как все продумано и красиво. Мне начинает нравится эта СУБД. -------------------- Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед) ... Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн) |
|||
|
||||
| s |
|
|||
|
Unregistered |
Заинтересовала эта задача. К сожалению с MySQL не работаю, а на MSSQL не проще будет так
|
|||
|
||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Весь прикол в том, что MYSQL ранее не поддерживала подселекты и хранимки. Следовательно с такими ограничениями решить в один запрос оказывается очень сложно и не рационально. -------------------- Теперь при чем :P |
|||
|
||||
| Settler |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 23.4.2008 Репутация: нет Всего: нет |
Доброй ночи! Бился сегодня над решением этой задачи, т.к. у себя на сайте нужно было выводить пользователей и кто где находится, только вместо цены были зарегестрированные пользователи, а в место валюты айпиадрес, теперь обновляю и смотрю какую страницу яндекс индексирует))) да и вообще кто где находится))
Вот под задачу вашу запрос будет выглядеть так (я даже удивися что так просто и работает)
+------------+-------+------+ | vdate | vname | vval | +------------+-------+------+ | 2000-01-02 | USD | 20.5 | | 2000-01-04 | EURO | 21.5 | | 2000-06-04 | EURO | 25.5 | | 2001-03-07 | USD | 30 | | 2005-01-07 | USD | 17 | | 2005-04-14 | EURO | 23 | +------------+-------+------+ отгруппируется ПО ДЕНЕЖНОМУ ЗНАКУ (который отсортируется относительно максимума даты) и выведеся это всё по максимальному значению цены и получится | 2005-04-14 | EURO | 23 | | 2005-01-07 | USD | 17 | можно выводить относительно даты, в запросе ORDER BY vval меняем на vdate - в данном конкретном примере вывод не поменяется но если строк в таблице много самых разных, то вывод будет другой Это сообщение отредактировал(а) Settler - 23.4.2008, 01:38 |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | MySQL | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |