|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Друзья, добрый день. Имеется одна с виду простая задачка, которая, однако плохо поддаётся. В базе есть таблица сделок(очень большая, миллионы записей) со ссылкой на клиента, плюс сама таблица клиентов(также огромная). У записей в каждой из таблиц есть период действия (см. пример с запросом ниже). "01.01.3000" - дата открытой записи. Цель состоит в том, чтобы "размножить" исходную запись сделки, разбив по периодам действия её и клиента к ней относящегося. То есть для сделки с id =1 результат должен получиться таким: Код: plsql 1. 2. 3. 4.
Пока удалось только собрать запрос, который срабатывает по одной сделке(если больше - получается каша, оно и понятно с FULL JOIN), и он явно далёк от хорошего. Код: plsql 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. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75.
Задача не разовая, предполагается её регулярное выполнение, пусть и с небольшим ограничениями объёмов. Подскажите, пожалуйста, в какую сторону копать, чтобы добиться более оптимального решения задачи во вменяемое время с учётом большого кол-ва данных. Изначально предполагалось решать одним запросом, но теперь рассматриваю любые варианты. Вообще насколько критично, если в большом запросе с конструкцией with происходит многократное использование объёмного подзапроса(как в примере выше при использовании union)? Oracle ведь не перечитывает каждый раз исходную таблицу, верно? Само собой оперативка тоже нерезиновая. Заранее благодарю за помощь. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2020, 20:32 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_zТо есть для сделки с id =1 результат должен получиться таким: Вы смешали даты из таблицы сделок и клиентов и считаете это верным результатом ? одно из решений Объединение временных промежутков ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2020, 07:20 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
123йй Dmitry_zТо есть для сделки с id =1 результат должен получиться таким: Вы смешали даты из таблицы сделок и клиентов и считаете это верным результатом ? Такова постановка задачи. То есть если у клиента поменялся какой-то атрибут, то текущая запись закрывается и открывается новая. Сделка с этим клиентом также должна побиться на соответствующие интервалы, даже если эти атрибуты в конечном счёте не попадают в итоговый набор данных. Но вариант, что таки-попадают я бы тоже предусмотрел, интересно, как составить запрос в этом случае. Клиенты взяты для примера, могут быть и другие сущности. За ссылки спасибо, погляжу. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2020, 13:35 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z, авторВообще насколько критично, если в большом запросе с конструкцией with происходит многократное использование объёмного подзапроса(как в примере выше при использовании union)? Oracle ведь не перечитывает каждый раз исходную таблицу, верно? В таких ситуациях может произойти temp table transformation - вынесение CTE во временную таблицу. Смотрите план на предмет такого такого элемента, да и вообще, смотрите план. :) ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2020, 10:36 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z За ссылки спасибо, погляжу. имхо У Вас задача (грубо говоря) оратная к "обьеденению" ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2020, 12:53 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Не вполне понятен требуемый алгоритм разбиения на периоды. Например, почему у вас нет в результате периода с 05.08.2019 по 06.08.2019. Также не понятно, почему есть период 01.01.2019 по 01.08.2019, а не по 02.08.2019. В общем, предлагаю свой вариант, может он поможет в решении задачи: все даты объединить в один столбец, а уже по нему считать периоды "с-по". Так для каждой даты "начала" брать дату "окончания" как ближайшую большую из дат. Код: plsql 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.
Результат: Код: plsql 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.05.2020, 22:41 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
SimonInBlues, Dmitry_z У записей в каждой из таблиц есть период действия (см. пример с запросом ниже). "01.01.3000" - дата открытой записи. обычно период действия непрырывный (нет пересечений и дырок) тогда задачка сводится к простому Код: plsql 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.
конечно надо у автора уточнять ... |
|||
:
Нравится:
Не нравится:
|
|||
04.05.2020, 10:26 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
SimonInBlues Не вполне понятен требуемый алгоритм разбиения на периоды. Например, почему у вас нет в результате периода с 05.08.2019 по 06.08.2019. Также не понятно, почему есть период 01.01.2019 по 01.08.2019, а не по 02.08.2019. Период с 05.08.2019 по 06.08.2019 - лишний. В исходных данных времени нет, но представьте, что запись действует до 05.08.2019 23:59:59, а следующая с 06.08.2019 0:00:00. SimonInBlues В общем, предлагаю свой вариант, может он поможет в решении задачи: все даты объединить в один столбец... Тоже пока пришёл к варианту "один столбец, пляшем от него". Stax, ваш вариант чрезвычайно затратный по ресурсам, если выполнять его не по одной записи. В таблице клиентов миллионы записей, в сделках и того больше. Дополню задачку. Из архитектурных ограничений - результат должен выводиться с помощью табличных функций. Плюс необходимо принудительно бить периоды по концам месяцов в зависимости от параметров, переданных в табличную функцию. На данный момент остановился на том, что в основном запросе склеиваю сделки с клиентами таким образом, чтобы получить записи вида: Код: plsql 1. 2. 3.
Далее отдельным запросом по каждой записи(табличная функция же) бью по периодам. На первый взгляд выглядит не очень из-за переключения контекста, но на практике миллион записей бьётся минуты за 2, что вполне сносно с учётом большого количества записей в источнике. Но теперь проблема в том, что в итоге получается достаточно много задвоенных записей, т.к. каждая из основного запроса обрабатывается отдельно. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.05.2020, 17:09 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z, Вам надо разбить все сделки (миллионы), или одну/одного клиента? если все, то надо тестировать, мож дистинкт будет быстрее not exists(select 1 from deals_base d where d.client_id=c.client_id and d.from_date=c.from_date) ) надеялся что есть индекс client_id, d.from_date ps с помощью табличных функций я б шел (фетчил) последовательно попеременно по двух курсорах (сделок и клиента) и в зависимости от дат пайпил, в том числе помесячно зыы про задвоение не понял, скорее бага алгоритма ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
05.05.2020, 17:47 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z, в таблице сделок для сделки больше одной строки допускается? Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
.... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
05.05.2020, 18:04 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Stax Dmitry_z, Вам надо разбить все сделки (миллионы), или одну/одного клиента? Все сделки со своими соответствующими клиентами, да. Stax я б шел (фетчил) последовательно попеременно по двух курсорах (сделок и клиента) и в зависимости от дат пайпил, в том числе помесячно Вот это я не понял. Типа в функцию с запросом клиентов залетать с конкретным id, который мы получили по сделке? А дальше? Stax зыы про задвоение не понял, скорее бага алгоритма Само собой, через какое-то время, возможно, удастся перекинуть сюда запрос, чтобы было понятнее. Stax Dmitry_z, в таблице сделок для сделки больше одной строки допускается? Разумеется. В качестве первичного ключа используется id_deal+to_date. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.05.2020, 18:10 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z Вот это я не понял. Типа в функцию с запросом клиентов залетать с конкретным id, который мы получили по сделке? А дальше? не разбиваем почти для всех сделок select * from table (f(x...даты например)) в f() курсор по сделках - внутренний по клиентах если чесно, лень кодировать IFы ... .... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
05.05.2020, 19:21 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z Вот это я не понял. Типа в функцию с запросом клиентов залетать с конкретным id, который мы получили по сделке? А дальше? шаблон Код: plsql 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. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76.
...... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
06.05.2020, 12:23 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Stax, здесь вы пытаетесь сортировать по символьному представлению даты. Код: plsql 1.
Результат будет зависеть от NLS_SORT, да и в принципе работает это так себе. Попробуйте с таким набором данных отсортировать: Код: plsql 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.05.2020, 18:50 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z Stax, здесь вы пытаетесь сортировать по символьному представлению даты. Код: plsql 1.
Результат будет зависеть от NLS_SORT, да и в принципе работает это так себе. Код: plsql 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.05.2020, 19:03 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Elic Если ты такой умный, то продемонстрируй NLS-ненадёжность именно этого отображения даты в строку для использования в качестве индекса ассоциативного массива: Код: plsql 1.
Не, не настолько умный. :) Это не основной аргумент, просто в какой-то статье вычитал, что нужно быть осторожным в плане символьных индексов. Каюсь, что в данный пример приплёл NLS_SORT. А по сабжу есть мысли? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.05.2020, 19:14 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
И по второму аргументу я тоже не прав. Когда сам тестировал подобное, в качестве индекса использовал более классическое представление дат - dd.mm.yyyy. В этом варианте, действительно, работает так себе. У Stax же представление yyyymmdd, и сортировка по нему работает корректно. Так что прошу прощения. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.05.2020, 19:29 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z А по сабжу есть мысли? Dmitry_z Дополню задачку. Из архитектурных ограничений - результат должен выводиться с помощью табличных функций. И чисто личное мнение: регулярное перемножения лярда на лям - бессмысленное с точки зрения практического смысла занятие. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.05.2020, 19:50 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Elic По мне - это облегчение/упрощение. Вполне возможно, только я пока не понимаю, как это удачно реализовать. Elic И чисто личное мнение: регулярное перемножения лярда на лям - бессмысленное с точки зрения практического смысла занятие. Тоже верно. Это задача классификации сделок в хранилище. Утешает тот факт, что в ежедневном режиме количество сделок таки будет вменяемым, а полноценный пересчёт будет происходить, например, раз в неделю. Однако за несколько часов он таки должен отрабатывать. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.05.2020, 21:14 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z тешает тот факт, что в ежедневном режиме количество сделок таки будет вменяемым, а полноценный пересчёт будет происходить, например, раз в неделю. Dmitry_z Однако за несколько часов он таки должен отрабатывать. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.05.2020, 07:42 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Elic Я может чего-то не понимаю, но как факты могут меняться задним числом, чтобы их постоянно пересчитывать из пустого в порожнее. Обсчитывай свежую делту. Могут поменяться правила классификации, поэтому пересчёт необходим. Взгляд в прошлое всё-таки будет ограничен месяцем-кварталом, однако и это огромный объём. Elic С таким подходом два часа со временем неизбежно выдут за сутки. С фатальнейшими последствиями для бизнеса, не так ли? Нашей команде архитекторы жёстко диктуют правила и рамки, к сожалению, на данном этапе мы практически ничего не можем изменить. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.05.2020, 09:31 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z Могут поменяться правила классификации, поэтому пересчёт необходим. Те, кто не могут инвалидировать подмножество (я подразумеваю малое) в связи с изменением чего-там, чтобы только его пересчитать, пересчитывают тупо всё. Так же проще :/ ... |
|||
:
Нравится:
Не нравится:
|
|||
07.05.2020, 09:38 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Dmitry_z Stax, здесь вы пытаетесь Пытался Код: plsql 1. 2. 3. 4. 5.
почему выбивает из-цикла не знаю мож для type t_dat is table of date index by использовать for i in vt_dat.first .. vt_dat.last loop неправильно из цикла вылетает после первого же pipe, при count=3 вторая итерация выбивает из ф-ции по no data found Код: plsql 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. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81.
.... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
07.05.2020, 09:49 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Обычно в таких случаях я начинал с того, что получал таблицу интервалов (union исторических периодов или через вспомогательную таблицу-календарь), затем по каждому интервалу получал исторические значения всех атрибутов, а затем снова агрегировал периоды (если требовалось). Результат получается избыточный, однако после этого итог проще понять и оптимизировать, чем пробовать сразу написать оптимальный запрос. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.05.2020, 11:06 |
|
Задача разбивки-размножения строк по периодам действия
|
|||
---|---|---|---|
#18+
Elic Тогда твой пример клиент-сделка неадекватен? Почему? Elic Те, кто не могут инвалидировать подмножество (я подразумеваю малое) в связи с изменением чего-там, чтобы только его пересчитать, пересчитывают тупо всё. Так же проще :/ Типа того. Бизнес хочет быть уверен, что после изменения правил и нажатия большой зелёной кнопки "счастье" все данные будут правильные и актуальные. Другой вопрос, что архитекторы пока не очень понимают, как это всё будет в реальном режиме работать. То есть с одной стороны можно было бы подмножество регулировать параметром табличной функции, но с другой - дополнительные арх. ограничения, в которых прописано, что параметры и вызовы табличной функции лежат в таблицах, а механизма быстрой корректировки и запуска с отсутствием коллизий нет. Stax, попробуйте добавить в исходные данные по сделке ещё одну строку с периодом. В результирующем наборе всё станет задваиваться, я пока на этом застрял. То есть в PL/SQL табличной функции ещё как-то можно было бы проверять, что такая запись уже была, однако в исходных таблицах записи лежат в произвольном порядке, а если сортировать такой объём - о нормальной производительности можно забыть. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.05.2020, 11:24 |
|
|
start [/forum/topic.php?fid=52&fpage=46&tid=1881282]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
47ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
97ms |
get tp. blocked users: |
2ms |
others: | 27ms |
total: | 212ms |
0 / 0 |