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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задачка на собеседовании.. как такое сотворить?.. 
:(
    Опции темы
Kurt
Дата 2.9.2005, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


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

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



Вспомнил, как ходил в прошлом году на собеседование. Мне тогда дали такую задачку:
есть таблица:
Код

CREATE TABLE mtest (
  vdate date default NULL,
  vname varchar(10) default NULL,
  vval float default NULL
)

Это таблица изменений цен на валюту (пусть, для простоты, это цена покупки).
Например, есть такие данные:
Цитата
+------------+-------+------+
| 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-01-07 | USD  |  17 |
| 2005-04-14 | EURO  |  23 |

Задачу предлагалось решить на MSSQL2000 и я как-то вывертелся через вложенный запрос, что явно очень не понравилось моим "экзаменаторам".
Прошли годы. На то место я не устроился, о чем, правда, не сожалею.
Однако, вот теперь задумался, как решить такую задачу на MySQL 3.23 - то есть до появления вложенных запросов?


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Sardar
Дата 3.9.2005, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

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



Цитата(Kurt @ 2.9.2005, 21:46)
получить актуальную стоимость каждой валюты

Это по последней дате? А разве нельзя сгруппировать по типу валюты, отсортировав по дате и снять первую строку с каждой группы?


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Kurt
Дата 3.9.2005, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


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

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



Одним запросом? (меня просили одним)
А ну, покажи, что-то я наверное совсем туплю..


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Sardar
Дата 3.9.2005, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

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



Цитата(Kurt @ 2.9.2005, 23:26)
А ну, покажи, что-то я наверное совсем туплю..

Да я сам туплю...
Пока порешал созданием временной таблицы... Но пятой точкой чую что можно одним запросом и эффективно...


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Secandr
Дата 3.9.2005, 07:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Связист
****


Профиль
Группа: Экс. модератор
Сообщений: 4043
Регистрация: 3.8.2003
Где: Russia, Volgograd

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



Может так:
Код

SELECT t1.vval, t2.vval FTOM mtest 't1', mtest  't2' WHERE t1.vname='EURO', t2.vname ='USD' ORDER BY t1.vdate DESC ,t2.vdate DESC LIMIT 0,1


Или ещё проще:
Код

SELECT * FROM mtest ORDER BY vdate DESC

И разобрать средствами php, допустим.


--------------------
Мышки плакали, кололись, но продолжали жрать кактусы (с) cisco
PM ICQ AOL   Вверх
Kurt
Дата 3.9.2005, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


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

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



Цитата
SELECT t1.vval, t2.vval FTOM mtest 't1', mtest  't2' WHERE t1.vname='EURO', t2.vname ='USD' ORDER BY t1.vdate DESC ,t2.vdate DESC LIMIT 0,1

Secandr
Количество валют нежестко задано. Их может быть две (как у меня в примере), а момет быть 50.
Поэтому этот запрос не будет решением.

Цитата

Или ещё проще:
Выделить всёкод SQL
Код

SELECT * FROM mtest ORDER BY vdate DESC

И разобрать средствами php, допустим.

Согласен. Но меня просили получить результат одним запросом. Без привлечения сторонних технологий типа PHP, ASP etc.


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Secandr
Дата 3.9.2005, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Связист
****


Профиль
Группа: Экс. модератор
Сообщений: 4043
Регистрация: 3.8.2003
Где: Russia, Volgograd

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



надо попробовать, есть пара дурных идей...


--------------------
Мышки плакали, кололись, но продолжали жрать кактусы (с) cisco
PM ICQ AOL   Вверх
Zipo
Дата 4.9.2005, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Тут вся трудность в дефолтной сортировке по дате. Физически данные будут храниться отсорированные по дате нарастающе (ASC). Т.к. заполняя таблицу мы каждый раз вводим дату большую чем предыдущая.
В MySQL данные храняться так же как и в MSSQL таблицах при отсутствии кластерного индекса.
Я не встречал создание индексов с указанием направления сортировки. В MySQL этого вроде и нету.
Задача решается таким запросом:
Код

SELECT vdate, vname, vval FROM (
       SELECT
             *
       FROM mtest
       ORDER BY vdate DESC
       ) AS tb
GROUP BY vname


Т.е. мы сортируем таблицу в нужном нам направлении по дате. Потом группируем по валюте и в итоге получим, то, что хотели.
Если кто знает как создать индекс с указанием направления сортировки (что бы данные физически хранились отсортированные по дате на DESC), то от вложеного запроса можно избавиться.
PM MAIL   Вверх
Kurt
Дата 4.9.2005, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


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

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



Zipo
К сожалению, задача таким запросом не решится. Более того, он даже не будет выполнен, т.к. синтаксически не верен.
У меня нет под рукой MySQL 4.1 (чтоб вложенные запросы работали), но я проверил свою догадку на MSSQL2000.
Во-первых, MSSQL не разрешает сортировку в подзапросе. Если не ошибаюсь, MySQL это также запрещает.
А во-вторых, даже если не обращать внимание на сортировку, то:
Цитата
..
Column 'tb.vdate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
..
Column 'tb.vval' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

То есть столбцы таблицы должны быть упомянуты либо в агрегатной ф-ции, либо в group by.
Уверен, это же правило распространяется и на другие СУБД.

P.S. В тестовой таблице, что мне предлагали, даты были перемешаны в случайном порядке. То есть не обязательно нижняя дата для каждой валюты больше верхней даты. Это просто я в примере так написал.


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Zipo
Дата 4.9.2005, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Я не писал если бы не проверил. У меня MySQL 4.1.7
Запрос корректно отрабатывает у меня.
Знаю, что MySQL не позволяет использовать LIMIT во вложенном запросе. О сортировках подобного не слышал.

Цитата
То есть столбцы таблицы должны быть упомянуты либо в агрегатной ф-ции, либо в group by.


Это скорее всего тоже ограничение MySQL 3.23
MySQL при группировке по определенным столбцам дает значения колонкам которые не вошли в группировку из первой записи которую он нашел эквивалентной группе. Группа у нас это валюта. Остальные поля получают значение из первой найденной строки для этой группы. Поэтому я и обратил Ваше внимание на сортировку.

В MSSQL сортировку использовать нельзя если во вложенном запросе нету TOP. С группировкой в MSSQL так непроходит.
PM MAIL   Вверх
Zipo
Дата 4.9.2005, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Для MSSQL оптимальным скорее всего будет процедура

Код

DECLARE @CountVal int
SELECT @CountVal = count(DISTINCT vname) FROM mtest;
EXEC ('SELECT TOP ' + @CountVal + ' vdate, vname, vval FROM mtest ORDER BY vdate DESC;')


Это конечно при условии, что обновление позиции происходит для всех валют. Т.е. не может быть обновление одной вылюты а потом другой через неделю.
PM MAIL   Вверх
S.A.P.
Дата 4.9.2005, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код

SELECT MAX( vdate ) , vname, vval
FROM `mtest` 
GROUP BY vname


так пойдет? Работает только в том случае, если курс валют не задан на перед...
PM MAIL   Вверх
Kurt
Дата 4.9.2005, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


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

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



Zipo
Хм.. Ваше решение в MSSQL через процедуру очень интересно. Возьму на вооружение. smile Спасибо. Хотя, конечно, это ограничение:
Цитата
Это конечно при условии, что обновление позиции происходит для всех валют. Т.е. не может быть обновление одной вылюты а потом другой через неделю.

сильно снижает практическое применение такого решения.
А вот с MySQL. Как бы добиться правильного результата на MySQL 3.23. Не знаю почему, но почти во всех (даже самых современных) дистрибутивах Linux я встречаю именно 3.23, кроме того, на многих хостингах также используется эта база. Ради спортивного интереса хотелось бы все-таки решить эту задачу для MySQL 3.23.

Perchilla
Не. Не пойдет. Вот, смотри, что возвращает твой запрос:
Цитата
mysql> select max(vdate), vname, vval from mtest group by vname;
+------------+-------+------+
| max(vdate) | vname | vval |
+------------+-------+------+
| 2005-04-14 | EURO  | 20.5 |
| 2005-01-07 | USD  | 20.5 |
+------------+-------+------+
2 rows in set (0.17 sec)

Согласись, цены явно не те.

З.Ы. Вот такие вот задачки дают у нас в деревне на собеседованиях. smile


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Ignat
Дата 4.9.2005, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Флудератор
****


Профиль
Группа: Экс. модератор
Сообщений: 4030
Регистрация: 19.4.2004
Где: غيليندزيك مدينة

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



Цитата(Kurt @ 4.9.2005, 21:53)
Вот такие вот задачки дают у нас в деревне на собеседованиях.

Не уверен, что они сами знают на нее ответ. Вполне вероятно, что это попытка решить задачку за счет соискателя.
Я тоже подумаю над этой задачкой. У меня сегодня такая-же выползла, только там четыре строки, а делать четыре запроса ломает..
Добавлено @ 22:10
Что-то мне сдается будет вроде этого, но не проверял.
Код

SELECT `vdate`, `vname`, `vval` FROM `mtest` GROUP BY `vname` ORDER BY `vdate`



--------------------
Теперь при чем :P
PM   Вверх
Kurt
Дата 4.9.2005, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


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

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



Цитата(Ignat @ 4.9.2005, 22:06)
Код

SELECT `vdate`, `vname`, `vval` FROM `mtest` GROUP BY `vname` ORDER BY `vdate`

Не, не то. Смотри, что получается:
Цитата
mysql> select vdate, vname, vval from mtest group by vname order by vdate;
+------------+-------+------+
| vdate      | vname | vval |
+------------+-------+------+
| 2000-01-02 | USD  | 20.5 |
| 2000-01-04 | EURO  | 20.5 |
+------------+-------+------+
2 rows in set (0.05 sec)




--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




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


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

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