Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Коллеги, приветствую! Не могу решить задачу. Возможно, это gaps and islands, но не могу нормально адаптировать примеры. Помогите! Итак, есть энное, в разрезе каждого ключа, количество примыкающих временных отрезков, либо DBEG следующего = DEND предыдущего, либо DBEG следующего = DEND + 1 день предыдущего: Код: 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. Нужно получить следующий результат: 1 1 ;1;2;3;4;5;6;7;8;9;20190101 2019011610 1 ;10;20190118 2019011911 2 ;11;12;13;14;20190102 20190109100 1 ;100; 20190103 20190109 Т.е. для каждой цепочки, соответствующей определенному ключу, указать, собственно ключ, N первой записи цепочки, перечень всех N цепочки, ну и даты начала цепочки и конца цепочки. Дело осложняется тем, что даты, в разрезе ключей, не попавшие точно на границу предыдущей цепочки с точностью до одного дня, даже если они попали внутрь цепочки - это уже другие цепочки! См. N=10 - вне цепочки, т.к. за пределами одного дня, 100 - внутри цепочки, но не попала точно на дату. Причем, вот ведь какая заковыка... Цепочка 100 - могла бы тоже стать родоначальницей собственной цепочки, т.к. к ней могли бы прицепляться узлы 2, 3 и т.д. Но этого быть не должно, т.к. эти узлы уже были использованы для построения цепочки, начинающейся в более раннюю дату. Однако, как я понимаю, одним запросом - это не решить, поэтому интересно любое решение! Примечание: Выращивание цепочки максимальной длины - не интересует. Для построении цепочки - берется первый подходящий узел, в порядке возрастания N. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.10.2019, 18:56 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
uaggster, вопросы: 1) Не логичнее сделать в первом случае цепочку 1;2;3;4;5;6;8;7;9;, т.к. 7-й может быть продолжением 8-го, а 8-й продолжением 7-го быть не может? 2)Ветвления как учитываются? такой набор будет одной цепочкой или двумя? 01-01 01-03 01-05 03-07 05-08 3) Почему 12 не является отдельной веткой, а продолжает 11-й элемент? он ведь не соответствует правилу авторDBEG следующего = DEND предыдущего, либо DBEG следующего = DEND + 1 день предыдущего: 4) почему цепочка для key=2 начинается с 20190102, если у 11-го элемента DBEG = 20190101? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.10.2019, 11:14 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
uaggster, Заведите отдельную таблицу календаря. От неё LEFT JOIN или OUTER APPLY на ваши данные и поверх этого агрегат или что-то такое ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.10.2019, 13:34 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Minamotouaggster, вопросы: 1) Не логичнее сделать в первом случае цепочку 1;2;3;4;5;6;8;7;9;, т.к. 7-й может быть продолжением 8-го, а 8-й продолжением 7-го быть не может? 2)Ветвления как учитываются? такой набор будет одной цепочкой или двумя? 01-01 01-03 01-05 03-07 05-08 3) Почему 12 не является отдельной веткой, а продолжает 11-й элемент? он ведь не соответствует правилу авторDBEG следующего = DEND предыдущего, либо DBEG следующего = DEND + 1 день предыдущего: 4) почему цепочка для key=2 начинается с 20190102, если у 11-го элемента DBEG = 20190101? Да, Minamoto , вы правы. Иллюстрация, приведенная мной - не совсем некорректна. Цепочка 1;2;3;4;5;6;8;7;9;. Но, в принципе, порядок перечисления узлов - не особо важен, главное, чтобы все узлы цепочки попали в перечисление. Но да, так правильнее. Ветвления не учитываются. Если через узел прошла цепочка - он выпадает из других цепочек. Т.е., на мой взгляд, должно быть что-то вроде такого: 1. Для данного key ищем N с минимальной датой начала. 2. Делаем узел текущим. 3. Для даты окончания текущего узла - ищем примыкающий узел, первый по N. Хотя, наверное, логичнее, из всех примыкающих узлов вначале выбрать а) те, которые начинаются в ту же дату, что и дата окончания примыкающего узла, и если таковых не найдено - то б) начинающиеся в следующий день. Выбираем 1 узел с минимальной N, ранее не помеченный как использованный ни в одной цепочке, относящейся к данному key. 4. Помечаем его в списке пути, дату его окончания - считаем датой окончания цепочки. 5. Повторяем 2-4 до исчерпания всех потенциальных начал цепочек для данного key. 6. Повторяем 1-5 для всех key. Но это - императивно. Можно ли как то это сделать с минимальным количеством курсоров? Ну, с циклами хотя бы. Это вроде как путь в орграфе, но построение пути или кратчайшего пути между двумя узлами - не нужно. Нужно определить, как далеко можно продвинутся, согласно правилам п.3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 08:57 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Появилось редактирование сообщений??? Дас ист фантастишь! ... И 20 лет не прошло. Спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 09:02 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
uaggster, почему строка 10 выпала из дерева, а строка 8 и 9 не выпала. Обе строки не попадают в правило продолжения цепочки, т.е. ожидаемый результат не верный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 11:41 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Владислав Колосовuaggster, почему строка 10 выпала из дерева, а строка 8 и 9 не выпала. Обе строки не попадают в правило продолжения цепочки, т.е. ожидаемый результат не верный.8 и 9 не выпадают - они как раз ложатся в условие, если 8 будет идти после 6, 7-я после 8, а 9 - после 7 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 12:08 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
uaggster, мне немного стыдно за код, плюс я не уверен, что учел все граничные условия, проверяйте на разных случаях. uaggsterВетвления не учитываются. Если через узел прошла цепочка - он выпадает из других цепочек. Вот это я не понял, поэтому сделал так, чтобы ответвление стало отдельной веткой. Собственно, вот. Свой кейс добавил для удобства проверки: Код: 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. 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 12:10 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
MinamotoВладислав Колосовuaggster, почему строка 10 выпала из дерева, а строка 8 и 9 не выпала. Обе строки не попадают в правило продолжения цепочки, т.е. ожидаемый результат не верный.8 и 9 не выпадают - они как раз ложатся в условие, если 8 будет идти после 6, 7-я после 8, а 9 - после 7 Насколько я владею арифметикой, порядок чисел такой: 6,7,8,9,10. То есть 8 никак не идет после 6, между ними 7. Т.е. "предыдущим" для 9 является 8, а не 7. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 12:30 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Набросал решение, наверняка можно оптимизировать и уменьшить кол-во сканов. Вывод самой цепочки зависит от версии SQL Server'a, можно сделать через STRING_AGG: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 13:16 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Remind, добавляем в цепочку к 10-му 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 13:26 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Minamoto, точно, забыл про самое главное. Думаю теперь должно работать. Код: 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 14:13 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Remind , вот одним местом чувствую, что здесь что-то не то! Код: sql 1. 2. 3. 4. 5. 6. 7. 8. Дело в том, что первое подходящее продолжение цепочки - не обязательно с большим N по отношению к текущему узлу. Подходящий N - может быть любым, в т.ч. и меньшим, чем текущий N. Да, из подходящих продолжений цепочки - выбираем с меньшим N. Нет, никто не гарантирует, что этот N больше N текущего узла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 15:03 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
Minamoto, в целом, мысль понял. Попробую покатать на примерах. Ну, после того как вкурю. Не могу понять, где лошадь припрягается, как обходится момент, когда кончилась одна цепочка с для данного key, а следующая цепочка для данного key должна стартовать изнутри интервала предыдущей цепочки, попадись в ней "непримыкающий узел". Ну, пример с узлом 100. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 15:12 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
uaggsterMinamoto, в целом, мысль понял. Попробую покатать на примерах. Ну, после того как вкурю. Не могу понять, где лошадь припрягается, как обходится момент, когда кончилась одна цепочка с для данного key, а следующая цепочка для данного key должна стартовать изнутри интервала предыдущей цепочки, попадись в ней "непримыкающий узел". Ну, пример с узлом 100.Это в delete. Мы сначала строим все "правильные" цепочки, потом в delete удаляем те варианты, которые включают узел, встречающийся в другой цепочке, но имеют айдишник выше, чем у другой цепочки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 15:24 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
uaggster, Сначала показалось, что монструозный WHERE в первой части CTE, предназначенный, чтобы найти правильные начала веток не нужен - мы можем построить вообще все варианты веток, и потом удалить неправильные. Оказалось - поторопился - если ветку с 10, 15 развернуть, чтобы она начиналась с большего N (заменить 10 на 50), то ветка разваливается, а с WHERE - нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 15:39 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
uaggster Remind , вот одним местом чувствую, что здесь что-то не то! Дело в том, что первое подходящее продолжение цепочки - не обязательно с большим N по отношению к текущему узлу. Подходящий N - может быть любым, в т.ч. и меньшим, чем текущий N. Да, из подходящих продолжений цепочки - выбираем с меньшим N. Нет, никто не гарантирует, что этот N больше N текущего узла. А жаль :) Попробую еще покурить, но похоже реально без рекурсии тут не обойтись. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 16:47 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#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. 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. 82. 83. 84. 85. 86. 1 2019-01-01 2019-01-16 1 2019-01-18 2019-01-21 2 2019-01-01 2019-01-09 3 2019-01-01 2019-01-08 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 18:11 |
|
||
|
Как агрегировать последовательность дат (возможно gaps and islands)
|
|||
|---|---|---|---|
|
#18+
a_voronin, у Вас классический gaps and islands, у автора не все так просто. Код: sql 1. 2. 3. 4. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2019, 18:41 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=39884331&tid=1687022]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
137ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
40ms |
get tp. blocked users: |
1ms |
| others: | 226ms |
| total: | 437ms |

| 0 / 0 |
