| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Составление SQL-запросов > ПОМОГИТЕ составить запрос |
| Автор: asdfghjkl 10.9.2009, 08:30 |
| http://ipicture.ru/ Необходимо выбрать из т.2.1.1. id, moment (первый), status, если status неизменен и >0, причем надо дополнительно посчитать длительность этого промежутка времени в минутах и вывести в столбец duration. Думаю, что-то вроде вложенного запроса (может ошибаюсь), внешний выбирает, внутренний проверяет статус, подсчет длительности: (конечный момент- начальный момент)*60. Но как прописать добавку нового столбца, хотя бы набросок? Какой тип запроса использовать? |
| Автор: Gluttton 10.9.2009, 08:47 |
| Так в чём конкретно проблема? Что именно не получается? |
| Автор: Akina 10.9.2009, 08:48 |
| Gluttton, она сама ни хрена не знает. http://forum.sources.ru/index.php?showtopic=281619&view=findpost&p=2361774 |
| Автор: asdfghjkl 10.9.2009, 08:55 | ||||
Грубость здесь не уместна, не хочешь помочь не надо, может не все такие снобы как ты. если внимательно посмотришь суть запроса изложена. Добавлено через 4 минуты и 14 секунд
не получается организовать проверку на статус, я так понимаю, что должен проходить по строкам пока татус не изменился, но надо запоминать момент. и еще не сталкивалась с добавлением в выходные данные нового столбца. Написано возможно использование сложного, коррелированного или вложеного запроса, думаю коррелированный запрос не подходит, а вот насчет сложного или вложеного не знаю. Добавлено через 11 минут и 6 секунд сейчас читала про сложные запросы, написано, что если необходимо во вложенных запросах использовать одну и ту же таблицу, то запрос должен быть коррелированным. |
| Автор: Zloxa 10.9.2009, 09:43 | ||
Думаю в задании ошибка. На каком основании посчитано duration = 120 для id =2 moment=14:00 - не ясно
|
| Автор: asdfghjkl 10.9.2009, 09:50 |
| СПАСИБО ОГРОМНОЕ. А можно немного пояснений начиная с 16 строки, плиз? Думаю в последней строки опечатка, а может для проверки специально так задумано. |
| Автор: Zloxa 10.9.2009, 09:56 |
| asdfghjkl, Этот запрос АФАИК сможет отработать только на Оракле. Возможно на PG. Какая у вас целевая платформа? |
| Автор: asdfghjkl 10.9.2009, 10:00 |
| Это задание, вроде как организация использует Oracle, но я сама работала только с MySQL. возможно как-то переписать? я вот начала разбирать, но не все понятно. |
| Автор: Zloxa 10.9.2009, 10:03 |
Как раз над этим сейчас и думаю. Если Gluttton меня опередит, будет ой как досадно |
| Автор: asdfghjkl 10.9.2009, 10:03 |
| Что происходит в: 20 select 21 s.* 22 , sum(start_of_group) over (partition by id order by moment) grp_id 23 from ( 24 select s.* 25 , decode(status,lag(status) over (partition by id order by moment),0,1) start_of_group 26 from s order by moment 27 )s 28 )s ? |
| Автор: Akina 10.9.2009, 10:08 |
Пока - нет. Если запрос на приведённых исходных данных даёт приведённый выход, это не значит, что логика получения ответа соответствует истинной. И на другом наборе входных данных может получиться хрень. Именно этого ты никак не можешь понять. Иными словами, модель чёрного ящика всегда приближённая. |
| Автор: Zloxa 10.9.2009, 10:12 |
| Строка 25 сравнивает статус со следующей по моменту в разрезе id строчкой, в случае если совпадает, выставляет 0, иначе 1. Получается еденичка проставляется для первого статуса в группе подрядидущих. Строка 22 считает накапливающую сумму по посчитанному в строке 25 значению в разрезе id в пореядке возрастания момента. Получается расчитывается какбы уникальный идентификатор группы подрядидущих. |
| Автор: asdfghjkl 10.9.2009, 10:32 | ||
А это одинаково для оракл и MySQL? откуда grp_id, я поняла, что это идентификатор повторяющих групп, почему он не указан в 25 строке? А для чего эта сумма? |
| Автор: Zloxa 10.9.2009, 10:35 | ||
Я же сказал. Это только для оракл. Может быть Постгри так же умеет. Потому что на основании значения, полученного в 25й, он расчитывается Думайте можете взорвать себе еще мозг моделью.. это вот точно ТОЛЬКО для оракла, прчем начиная только с 10й версии работает по тому же принципу
Добавлено через 6 минут asdfghjkl, А может ну его? Если вы поакажете решение на собеседовании, но затруднитесь повторить на практике в оффисе, врядли вы пройдете испытательный срок. Может куда попроще попробовать сунутсья, где требования чуть мене высокие? |
| Автор: asdfghjkl 10.9.2009, 10:45 |
| Не злитесь, просто мне это объяснять и я волнуюсь, это не просто задание нудного препода. Может я совсем безнадежна, но сдаваться не хочется. Насчет grp_id, я всегда думала, что если что-то вычисляется, то должно указываться куда это все поместить. А сумма- это количество групп, или количество записей в группе? Вроде должно быть записей, но если считается по grp_id... |
| Автор: asdfghjkl 10.9.2009, 11:52 | ||
я не хочу слишком умное решение, хотя бы просто показать, что пробовала. Дело в том, что последний раз работала с БД месяцев 10 назад, навык утрачен, но хочу поднапрячся. А там у них свое дополнительное обучение будет, думаю справлюсь. Это кстати, часть задания, сложная. Что попроше я уже сделала, они одобрили, попросили, мои размышления по поводу вот этого. |
| Автор: Zloxa 10.9.2009, 12:27 | ||||
| На MySql должно проканать. Если пара id, duration не уникальна - будут завихрения(как и в первом запросе). Принцип - тот же.
Добавлено через 14 минут и 42 секунды Перемудрил. Проще:
|
| Автор: asdfghjkl 10.9.2009, 12:55 |
| Спасибочки, буду разбираться перед отправкой, кстати все намного понятней для моего восприятия, только один вопрос: start_of_group еще кое-где встречала, это имеет специальное значение или такое название? |
| Автор: Zloxa 10.9.2009, 13:03 |
Нет. Это общепринятое название метода. Я даже знаю где Вы это встречали. Обычно так называют это поле для того, чтобы читающему было понятно о чем речь, и можно было легко найти по ключевому слову. На том ресурсе, где Вы встерчали этот термин, уже давно гнушаются отвечать на подобные вашему вопросы. Типичный ответ там на ваш вопрос - "STFF start_of_goup" |
| Автор: asdfghjkl 10.9.2009, 14:10 |
| Правильно я поняла?: В строках 25, 26- строка таблицы соединяется сама с собой. В 24- проверка на неизменность статуса, группируются блоки. Я наверное задам глупый вопрос, но все же: что происходит в 27, 29-32? |
| Автор: asdfghjkl 10.9.2009, 14:43 |
| Пересмотрела, наверное :в 25-31 соединение двух последовательных строк по одному id с присвоением grpid. в 23- устанавливается 1 в первый отличный статус. Засмейте меня, но не пойму зачем сумма? |
| Автор: Zloxa 10.9.2009, 15:12 | ||
Сумма нужна для того, чтобы сложить единички. Нам нужно выделить группы подряд идущих значений. Для того, чтобы можно делать группировку, нам необходимо чтобы строки в пределах одной группы имели одинаковое значение по полю группировки. Необходимо так же, чтобы это значение различалось у разных групп. Что мы можем сделать? Мы можем сравнить каждую строчку со следующей и найти начало( или конец) группы. Но как присвоить идентификатор всей группе? Пометить начало каждой группы единичкой и пустить накапливающую сумму по ней. В результате получим такую сумму:
Так как единички определяют начало группы, то сумма этих единичек обозначает порядковый номер группы Теперь по этому значению можно группироваться. |
| Автор: Zloxa 10.9.2009, 15:52 | ||
| Еще один способ. Идея заимствована у http://forum.vingrad.ru/index.php?showtopic=268586&view=findpost&p=1937016. Должно работатать еще и на MS SQL. Достаточно легко переписывается на каунт. Оверхеда меньше чем в предыдущем варианте. При первом взгляде кажется что может дать не верный результат. При втором взгляде кажется что первый взгляд - кажется. Так что если ктото придумает на каких исходных данных результат окажется не корректным(кроме не уникальных id,moment), буду только рад.
|
| Автор: asdfghjkl 10.9.2009, 15:56 |
| Ну спасибо, а я дурак думала, что единички складываются в одну общую сумму по всей таблице, т.е. сумма будет показывать количество групп. |
| Автор: Simpliest 10.9.2009, 23:14 |
| Угу, тред читается на одном дыхании А последний момент, просто кульминация. Конспирология в действии. Это я к чему, да к тому, что знание SQL как езда на велосипеде. Ты можешь забыть нюансы, но не разучится ездить. P.S. не люблю я таких ТС :( |
| Автор: Gluttton 11.9.2009, 00:07 | ||||||||||||
Жутко хотелось поучаствовать, но на работе сегодня был загруженый день... Да и когда за решение взялся не всё так просто оказалось Итак...
Я думаю, что это задание не столько на "результат" сколько на "рассуждение" и возможно это умышленно внесенная ошибка, но если подходить к решению исключительно формально, то можно предположить, что для id=2, необходимо выводить не просто продолжительность, а сумму продолжительности с накоплением. О как Начну со своего крокодила
Не буду коментировать этот код, а прокоментирую приведенный ниже. Что бы хоть как то облагородить запрос использовал CTE (а вот тут уже начинаються отличия серверов, на сколько знаю, на MS SQL должно пойти) и вот, что получилось:
Отмечу, что второй запрос преобразуется в первый простым "разворачиванием" CTE, без всяких любых других преобразований. А теперь - картинки На следующих исходных данных: ![]() Запрос вернет следующие данные: ![]() "Усилим" тестовый набор данных: ![]() Кстати на эти данные показывают следующую неопределенность: прерывать ли подсчет периода при смене id, но при том же status? Я например прерываю, а может и не нужно? Получаем результат: ![]() Т.е. сумма с накоплением для id=2 работает. Теперь о запросе. Очевидно, что это
"Шелуха" для обеспечения выдуманой мною суммы с накоплением... Внутри остается (убрал преобразование интервала времени в целое, что бы глаза не мозолило):
Вот результат запроса для меток 1-7: ![]() А на метках 11-18, мы для каждого отобраного (на этапе 1-7) значения moment находим максимальную границу (при "неприрывном" status и id) и вычисляем их разницу... Как всегда, запрос у Zloxa лаконичнее |
| Автор: Zloxa 11.9.2009, 00:17 |
| Gluttton, спасибо что поддержал. Сени уже поздно, и я уж малость вина выпил. Завтра повзрываю себе мозг твоими выкладками. Оппа... в FB есть? Для меня новость, спасибо ! upd А в with FB рекурсию держит? как это в MSSQL и DB2. Оракля не держит, а жаль... мне кажется чудная возможность, чудное поле для извращений |
| Автор: Gluttton 11.9.2009, 12:51 | ||
Зато теперь я знаю, что такое upd Да поддерживает (используется в частности для обхода, деревьев). |