|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
Коллеги, помогите придумать выражение для сортировки. Второй час туплю, уперся как баран! Есть последовательность дат (тип datetime). Даты могут многократно повторяться. Необходимо отсортировать ее по степени близости к значению заданной переменной @date, по следующему правилу: 1. Даты, которые ближе, по модулю, к указанной дате - имеют меньший вес, чем те, которые дальше (по модулю) 2. Даты, которые расположены на одинаковом, по модулю, расстоянии, но по разные стороны от @date, имеют разный вес. Дата в прошлом от @date - имеет меньший вес, в будущем от @date - больший вес. 3. Сортируем от меньших весов - к большим. 4. Точность сравнения - поминутная. 5. Две даты, различающиеся только секундами - одинаковые по весу. Есть нюанс. Отобрать нужно записи с датой из top 10 из списка ближайших, но исходная таблица - содержит примерно миллиард (утрирую, но не сильно) записей. Причем иногда записи идут очень густо, десятки тысяч в окрестностях часа, иногда - лакуны по неделе между последовательными записями. Тривиальное решение - взять datediff от даты в записи и точки @date в минутах, вычислить abs от этого, а потом прибавить 0.1*sign от этого datediff - не прокатывает, т.к. никакими индексами это не ускорить, и, как результат, выборка будет длиться вечно. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 20:03 |
|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
uaggster, для знака надо сделать колонку 0/1, а не 0.1*sign. И сортировать по разнице и знаку. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 20:13 |
|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
если нужен +/-10 ближайших соседей, то можно попробовать создать индекс по дате и использовать аналитические функции. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 20:19 |
|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
Как-то так Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 20:24 |
|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
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.
PS помахнулся, выборка нерепрезентативная, надо использовать разницу по модулю. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 20:38 |
|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
invm Как-то так Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Да, тоже нечто подобное думал, но недопилил. Проблема в том, что нужно отобрать записи with ties. Т.е, определяем окрестность из 10 самых близких к точке дат, с округлением до минуты. Потом отбираем все записи с этими датами. Получается, что для записей раньше точки, нужно отобрать записи с Dense_rank() over (order by округленная до минут дата) =< 10, и аналогично - позже точки. Потом - определить в этой локальной области топ 10 по вышеописанным правилам. А потом для крайне ранней и крайне поздней точек - выбрать все записи, between между ними. Как то слишком сложно... ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 21:54 |
|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
uaggster Получается, что для записей раньше точки, нужно отобрать записи с Dense_rank() over (order by округленная до минут дата) =< 10, В голову приходит только один вариант: - в таблицу добавить выч. столбец вида datediff(mi, convert(datetime, '19000101', 112), [Дата]) as [Минуты], плюс индекс по нему - индексированное представление Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Тогда можно будет по представлению делать отбор и лезть за данными в основную таблицу. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.07.2020, 11:50 |
|
Предикат для сортировки по близости к определенной дате
|
|||
---|---|---|---|
#18+
Если создать колонку, заполненную разницей между минимальной датой таблицы и датой каждой строки, то задача достаточно просто решается, надо вычислить разницу между минимальной датой и переданной и отобрать по полученному смещению диапазон строк. Однако, если минимальная дата будет изменяться, то придется пересчитывать весь массив. С другой стороны, "минимальной" может служить фиксированное значение, например 19000101 и пересчитывать не понадобится. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.07.2020, 12:27 |
|
|
start [/forum/topic.php?fid=46&fpage=54&tid=1685882]: |
0ms |
get settings: |
11ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
35ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
51ms |
get tp. blocked users: |
2ms |
others: | 19ms |
total: | 155ms |
0 / 0 |