|
|
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
Друзья, помогите ботанику, пожалуйста. Как сделать рейтинг вида "Больше всех Черных драконов убил герой Горыныч; Красных - герой Добрыня, ...", понятно даже мне. А как средствами SQL сделать рейтинг вида "Больше всех Черных драконов убили (в порядке убывания количества убиенных) герои Горыныч, Добрыня и Зингельшухер; Красных - ..."? С LIMIT в подзапросах меня законно шлют лесом. Если слишком туманно, то могу привести структуры и пр. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2014, 08:36:34 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdoc, Так и пишите запрос: Выбрать вид дракона, отважный герой, сумма количества убиенных из хранилища убитых драконов с группировкой по виду дракона и отважному герою и сортировкой по виду дракона, количеству убиенных в по убыванию. При чем здесь PostgreSQL? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2014, 10:53:15 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
/\/\/\/\/\/\, Когда я хочу выбрать для каждого вида юнитов по одному рекордсмену, то я так и пишу, спасибо. Однако, я хочу для каждого вида юнитов выбрать по три рекордсмена, в порядке убывания их рекордов. Пока не получается, хотя чую, что задача почти из учебника. Имею структуры: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.07.2014, 11:47:47 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdoc, Вариант 1: посмотрите в строну group by c последуюшей обработкой результата через window function http://www.postgresql.org/docs/9.3/interactive/tutorial-window.html + http://www.postgresql.org/docs/9.3/interactive/functions-window.html (и на всякий случай заодно подумайте что вам нужнее row_numer или rank или dense_rank) Вариант 2: вместо LIMIT в подзапросах - сделайте тоже самое через LATERAL JOIN (он как раз для задачи когда надо выполнять подзапросы возвращаюшие несколько строк). --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.07.2014, 12:50:34 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, Так и подозревал, что всё упрется в оконные функции. LATERAL, как я понял, пришел к нам в 9.3, а живу пока на 9.1. Хотя, чем не повод переехать. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.07.2014, 15:02:07 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdocMaxim Boguk, Так и подозревал, что всё упрется в оконные функции. LATERAL, как я понял, пришел к нам в 9.3, а живу пока на 9.1. Хотя, чем не повод переехать. Спасибо.ну почему же. есть третий путь -- через CTE "WITH RECURSIVE" вот тут http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=969733&msg=13171811 есть даже некая почти удачная реализация чего-то похожего (если у вас есть "матвью" итогов, индексированное составным, в т.ч. по итогам -- это будет побыстрее. если такого "матвью" нет - оконные над агрегатами, как советуют, - лучший выбор). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.07.2014, 10:49:36 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
Отчитываюсь. Дано: герои убивают в битвах юнитов разных рас, уровней и подуровней. Задача: получить для каждого типа юнитов заданной расы трех лучших героев, убивших максимальное их количество в одной конкретной битве. Данные хранятся в таблицах: Типы юнитов. 215 строк. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. Детальная статистика. 18 миллионов строк. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. До текущего момента я выбирал все типы юнитов нужной расы (их 14) и для каждого в цикле отдельным запросом получал нужную тройку рекордсменов из детальной таблицы. На всё уходило порядка 30 секунд :о( Результат, конечно, кэшировал, но был сильно недоволен. По совету бывалых товарищей (спасибо им огромное) попытался погрузиться в оконные функции и соорудил запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. Вот его explain: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 20 секунд - уже лучше. Запрос к базе один, а не 14. Однако, вопросы: 1. Нет ли ошибок в логике запроса? 2. Что-то где-то можно ли улучшить, кроме как серверное железо? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 11:47:15 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdoc, т.к. у вас уже есть собранная материализованная статистика, то вместо окон вам нужен составной индекс на статистику по Код: sql 1. (комбинацию ASC|DESC -- из ваших хотелок, хотя можно по всякому) а остальное внутри ключевого набора (рассы,уровня,подуровня) отбирать без всяких окон -- простым селектом ORDER BY ({keys} ,count DESC) limit 3. как это сделать сразу для кучки (чтобы пройтись вдоль индексов всего по 3 записи -- можете покурить на тему последнего поста по ссылке, но проще функцией с прямым перебором ключевого набора в LOOP, чем через CTE хотя и то -- как видно по ссылке -- возможно). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 12:24:13 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
qwwq, хотя я кажжется не вчитался, счас пересмотрю ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 12:25:41 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
вам, похоже, вообще достаточно индекса по (to_tunit_id,count [DESC]) + техники прогона только LIMIT по индексу в рекурсивном cte ли, в лупе по to_tunit_id ли. извините, что проглядываю наискосок. не вчитываясь ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 12:31:33 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
qwwq, спасибо. Сижу и смотрю в бездну своего незнания SQL. С ходу тревожит мысль о ресурсоёмкости включения count в индекс на таблице в 20КК записей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 13:18:13 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdocqwwq, спасибо. Сижу и смотрю в бездну своего незнания SQL. С ходу тревожит мысль о ресурсоёмкости включения count в индекс на таблице в 20КК записей. в любом случае постройте индекс на макете. лямов на 1-2. отработайте простой запрос {LIMIT 3} по unit_id и фиксированному набору ключей. Соорудите CTE или ф-ю с LOOP ... RETURN QUERY -- они строятся идентично, прогоном по таблице юнитов (unit_id), или их подвыборке. Главное -- это запинать (фрагмент) на тот же план, что и индивидуальный запрос по фиксированному unit_id. А уже результат повяжите на справочники. ну и индекс в бою стройте CONCURRENTLY . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 13:48:45 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
например, (опять не вчитываясь, простите, т.к. "пусть лошадь думает, у ей голова большая) ) перелицовываем механически (массовой заменой) пример по ссылке под вас (вроде бы не вру, но вчитываться ломает -- поползайте с лупой сами): тест-кейс: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. план: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 14:07:19 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
qwwq, это какая-то магия :о) Ушел гонять с лупой крестьян на тестовом сервере. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 14:21:06 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdoc, на самом деле это всё крутится вокруг вот этой техники http://www.sql.ru/forum/882778/bystryy-podschet-distinct-values-po-indeksirovannym-polyam?mid=11326416#11326416 причем 1. вам дистинкт unit_id извлекать не нужно -- он у вас в справочнике юнитов сидит битым словом. 2. lateral замаскированный в postgresl даже 9.1 есть, просто он выглядит например как Код: sql 1. - и в этом виде немного неудобен (, если вам нужно lateral по нескольким полям (в добавок к вычислительным утяжелениям -- запаковкам/распаковкам)). вся же идея индексации в том, что она нужна внутри этого (так или иначе состряпанного) lateral-подзапроса -- для скорости перебора ORDER BY ..LIMIT . Только и всего. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2014, 15:44:38 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
Докладываю. Запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. В результате мгновенно получаю рейтинги для всех сразу типов юнитов, что великолепно. Но. Потерялась возможность фильтровать по to_hero_id: "взять только героев 10 уровня" или "взять только варваров". И это невыносимо печально. Вернее, такая возможность есть, но при попытке прилепить нужную таблицу для фильтра, время запроса приближается в таковому для варианта с оконной функцией. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.07.2014, 09:25:27 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdoc, вы таки полазьте еще в теме мексима -- чтобы понять, что вам на самом деле важно, а что нет. (я уже писал, что часть механически преобразованного запроса занимается извлечением дистинкта по unit-ам из вашей отдельной таблицы, что вам не нужно. т.е. в терминах 9.3. у вас был бы идеальный план изначальной задачи (с предложенным индексом) по запросу вида: Код: sql 1. 2. 3. 4. 5. 6. 7. или, для 9.1. ( без последующего расщепления искусственной строки--компаунда [, что несложно]) Код: sql 1. 2. 3. 4. 5. 6. 7. т.е. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Код: sql 1. 2. 3. 4. 5. 6. 7. далее начинаем морщить репу: --hero-ев у нас до heras, левелов (или рас) мало, т.ч. если нам надо по левелу или еше как (по расе) -- то ничего путного с индексным поиском не получится. (можно правда ожидать , что в поисках по расам если идти влоль нашего индекса, но не на глубину 3, а "до тех пор, пока не" встретится 3 хира нужной расы -- идти придется недалеко. если расы равносильны, и все близки к рекордам. А вот для левела 1 этого ждать явно не приходится [они ожидаются в хвосте]) поэтому для таких запросов наш матвью статистики неудачно собран. в него надо добавить уровни и расы в явном виде ( денормализация ). и, соответственно запросам, составные индексы с левельными и расовыми префиксами. (после чего задача сведется к разновидности предыдущей). а пока считайте нормальным, что так. да, и если вам придется считать абсолютных рекодсменов (а не "в одно-батальных" ) -- вам тоже придется свернуть всю вашу таблицу (в 20КК) и только потом окошком просматривать. Если конечно вы не делаете свертку--матвью заранее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.07.2014, 10:27:03 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
qwwqвы таки полазьте еще в теме мексима -- чтобы понять, что вам на самом деле важно, а что нет. (я уже писал, что часть механически преобразованного запроса занимается извлечением дистинкта по unit-ам из вашей отдельной таблицы, что вам не нужно.Я пытаюсь. Хотя, пара десятков мс меня уже более чем устраивает, сами понимаете. qwwqпоэтому для таких запросов наш матвью статистики неудачно собран. в него надо добавить уровни и расы в явном виде ( денормализация ). и, соответственно запросам, составные индексы с левельными и расовыми префиксами. (после чего задача сведется к разновидности предыдущей).Да. Тем более, что level там должен бы быть изначально - моя ошибка планирования. У героев он же растет, а в рекорде должен оставаться фиксированным. Правда, при каждой необходимости в денормализации сердце кровью-то обливается. qwwqда, и если вам придется считать абсолютных рекодсменов (а не "в одно-батальных" ) -- вам тоже придется свернуть всю вашу таблицу (в 20КК) и только потом окошком просматривать. Если конечно вы не делаете свертку--матвью заранее.Уже делаю, правда с другими целями. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.07.2014, 11:34:30 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
qwwq, А вот и серебряная пуля - "идеальный план изначальной задачи (с предложенным индексом)", спасибо Вам. Запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. Любые нужные рейтинги с любыми нужными фильтрами за крайне вменяемое время. Ура. Пока не понял, почему иногда тройка рекордсменов бывает таки не отсортирована по count, не смотря на ORDER BY s.count DESC, но, думаю, разберусь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.07.2014, 12:13:08 |
|
||
|
Составные рейтинги средствами SQL
|
|||
|---|---|---|---|
|
#18+
phdoc<> Пока не понял, почему иногда тройка рекордсменов бывает таки не отсортирована по count, не смотря на ORDER BY s.count DESC, но, думаю, разберусь.потому что последним в плане у вас идет пересортировка. Код: plaintext выпарсите counts из строки, как под спойлером -- и добавьте его в ключи окончательной сортировки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.07.2014, 13:06:30 |
|
||
|
|

start [/forum/topic.php?fid=53&tid=1998569]: |
0ms |
get settings: |
7ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
455ms |
get topic data: |
11ms |
get forum data: |
4ms |
get page messages: |
69ms |
get tp. blocked users: |
2ms |
| others: | 224ms |
| total: | 792ms |

| 0 / 0 |
