Как найти минимальный интервал времени

Find the “median timestamp range” which has minimal summary difference for given “arbitrary number of timestamps”.

If the amount of “arbitrary timestamps” is odd then this is the median timestamp. Take the timestamp equal to this median. If such timestamp not exists then take any timestamp within the range of the timestamps adjacent to the median timestamp or, if no such timestamp, take the timestamp closest to this range.

If the amount of “arbitrary timestamps” is even then this is a range between two median timestamps. Take any timestamp within this range or, if no such timestamp, take the timestamp closest to this range.

In both variants “closest timestamp” means “the timestamp which has minimal amount of arbitrary timestamps between self and closest range border, if there are a couple of such timestamp then take closest by the difference”.


We need not formula/theory but practical solution. Steps:

  1. We have an array of “data timestamps”. Let’s say it is DTS[1..X], it contains X timestamps.
  2. We have an array of “arbitrary timestamps”. Let’s say it is ATS[1..N], it contains N timestamps.
  3. Calculate the indices of two median elements in ATS (for odd-amount array this will be the same element). N1 = (N+1) MOD 2 ; N2 = (N+2) MOD 2.
  4. In DTS – find the timestamp DTS[K1] closest but not above ATS[N2] and the timestamp DTS[K2] closest but not below ATS[N1].
  5. Calculate “summary distance” for DTS[K1] and DTS[K2].

If the sums are equal then both elements and all elements between them (yes, they may be not adjacent in this case!) are the solution.

If they differs then the element with least sum is a solution. It seems that in this case cannot be a couple of solutions (but you may test its neighbors for to ensure).


Why this must work?

Imagine that AST contains 2 ts only. Take one DST between them, it has some difference sum. Move it 1s left. The distance to left ATS decreases by 1s, to right – increases by 1s, and total sum is unchanged. Move one more, and again… and the sum is constant until we reach left ATS. When we cross it the sum will increase by 2 for each 1s move.

Now imagine that we have 3-element ATS. Again take one DST and put it over the middle AST. Move to left or to right by 1s – partial sum to left/right ASTs will not change, distance to middle will increase by 1s, total sum will increase by 1s. Move more – when we cross the extreme ATS the sum will increase by 3 for each step…

Expand this to 4, 5, … element in ATS. The timestamp which has minimal sum matches the median timestamp or median timestamps range. Moving away from it increases the sum, crossing a timestamp increases increasing rate.

#python #mysql #sql #performance #timestamp

#python #mysql #sql #Производительность #временная метка

Вопрос:

Итак, представьте, что у меня есть база данных с идентификаторами и меткой времени:

 ID.      Time_Stamp_Col

id1.     2017-10-16 17:54:28
id2.     2016-09-13 17:14:17
id3.     2019-10-01 19:30:37
id4.     2017-08-27 20:55:30
id5.     2017-11-19 10:56:15
id6.     2018-02-12 09:59:24
  

и произвольное количество временных меток (2 для этого примера):

 2018-02-12 09:55:29
2017-11-19 10:21:12
  

Как мне вернуть столбец, содержащий минимальный timestampdiff между Time_stamp_Col и произвольным количеством временных меток?

(Я использую python, поэтому я полностью согласен с созданием цикла для генерации повторяющегося текста в соответствии с произвольным количеством временных меток)

У меня это пока:

 SELECT 
    LEAST(DATEDIFF('2018-02-12 09:55:29',
                    b.Time_Stamp_Col),
            DATEDIFF('2017-11-19 10:21:12',
                    b.Time_Stamp_Col)),
FROM
    DataBaseInQuestion b
  

Но это так невероятно медленно. DataBaseInQuestion содержит 14 миллионов строк. Есть ли более быстрый способ?

Комментарии:

1. Если вам нужно вернуть 14 миллионов строк, ваш запрос будет медленным.

Ответ №1:

Найдите «средний диапазон временных меток», который имеет минимальную итоговую разницу для заданного «произвольного количества временных меток».

Если количество «произвольных временных меток» нечетное, то это средняя временная метка. Возьмите временную метку, равную этой медиане. Если такая временная метка не существует, тогда возьмите любую временную метку в диапазоне временных меток, прилегающих к средней временной метке, или, если такой временной метки нет, возьмите временную метку, ближайшую к этому диапазону.

Если количество «произвольных временных меток» равно, то это диапазон между двумя средними временными метками. Возьмите любую временную метку в этом диапазоне или, если такой временной метки нет, возьмите временную метку, ближайшую к этому диапазону.

В обоих вариантах «ближайшая временная метка» означает «временную метку, которая имеет минимальное количество произвольных временных меток между self и ближайшей границей диапазона, если есть пара таких временных меток, тогда возьмите ближайший по разнице».


Нам нужна не формула / теория, а практическое решение. Шаги:

  1. У нас есть массив «временных меток данных». Допустим, это DTS [1..X], он содержит X временных меток.
  2. У нас есть массив «произвольных временных меток». Допустим, это ATS[1..N], он содержит N временных меток.
  3. Вычислите индексы двух медианных элементов в ATS (для массива с нечетным количеством это будет один и тот же элемент). N 1 = (N 1) MOD 2 ; N 2 = (N 2) MOD 2.
  4. В DTS — найдите временную метку DTS [K 1], ближайшую, но не выше ATS [N 2], и временную метку DTS [K 2], ближайшую, но не ниже ATS [N 1].
  5. Вычислите «суммарное расстояние» для DTS [K 1] и DTS [K 2].

Если суммы равны, то оба элемента и все элементы между ними (да, в этом случае они могут быть не смежными!) Являются решением.

Если они отличаются, то элемент с наименьшей суммой является решением. Кажется, что в этом случае не может быть пары решений (но вы можете проверить его соседей, чтобы убедиться).


Почему это должно работать?

Представьте, что AST содержит только 2 ts. Возьмите одно летнее время между ними, оно имеет некоторую сумму различий. Переместите его на 1 секунду влево. Расстояние до левого ATS уменьшается на 1 с, до правого — увеличивается на 1 с, а общая сумма не меняется. Переместите еще один, и снова … и сумма будет постоянной, пока мы не достигнем левого ATS. Когда мы пересечем его, сумма будет увеличиваться на 2 за каждый 1-й ход.

Теперь представьте, что у нас есть 3-элементный ATS. Снова возьмите одно летнее время и поместите его поверх среднего AST. Переместитесь влево или вправо на 1 секунду — частичная сумма для левых / правых точек не изменится, расстояние до середины увеличится на 1 секунду, общая сумма увеличится на 1 секунду. Двигайтесь дальше — когда мы пересекаем крайние точки, сумма будет увеличиваться на 3 для каждого шага…

Расширьте это до 4, 5, … элемента в ATS. Временная метка с минимальной суммой соответствует средней временной метке или среднему диапазону временных меток. Отклонение от него увеличивает сумму, пересечение метки времени увеличивает скорость увеличения.

Комментарии:

1. Я не уверен, что полностью понимаю /: Как это приведет к кратчайшей разнице во времени между строкой и произвольными временными метками?

2. @Travasaurus Добавлены некоторые пояснения.

Какой отрезок времени считается минимальным в физике?

Leon Polinezi

3 октября 2017  · 2,2 K

На самом деле вопрос не имеет смысла поскольку большинство физиков сейчас сходятся во мнении, что расстояние и время это не фундаментальные величины. Типа как температура есть мера кинетической энергии атомов и молекул, время и пространство появляется только на (относительно) макроскопическом уровне.

Не может существовать минимального интервала времени или расстояния поскольку их можно растянуть/сократить посредством перехода к другой системе отсчета (преобразования Лоренца). 

Нарушений Лоренц-инвариантности не обнаружено, следовательно минимальных длин и времен быть не может.

720

Я понимаю,что не в тему,но хочу вставить свои 5 копеек.Температура не есть мера кинетической энергии молекулы. Она… Читать дальше

Комментировать ответ…Комментировать…

Я полагаю, что ответ на ваш вопрос – Планковское Время.
Это то время, за которое частица, без массы, пройдет планковскую длину.
Сразу скажу, что планковская длина, это некое минимальное расстояние, на котором само понятие длины перестает существовать. И это, примерно, 10^-35 метров.
Так вот, те крошечные доли крошечных долей секунды и будут – тем самым минимально…
Читать далее

306

Комментировать ответ…Комментировать…

У меня есть таблица MySQL, в которой записываются события, полученные для пользователя, и дата получения события.

Date                    User

2012-01-21 18:30:02     AAA
2012-01-21 18:30:05     AAA
2012-01-21 18:30:08     AAA
2012-01-21 18:30:11     AAA
2012-01-21 18:30:15     AAA
2012-01-21 18:30:18     AAA
2012-01-21 18:30:21     AAA
2012-01-21 18:30:23     AAA
2012-01-21 18:30:26     AAA
2012-01-21 18:30:29     BBB
2012-01-21 18:30:32     BBB
2012-01-21 18:30:33     BBB
2012-01-21 18:30:37     BBB
2012-01-21 18:30:40     BBB
2012-01-21 18:30:42     BBB
2012-01-21 18:30:44     BBB
2012-01-21 18:31:01     BBB
2012-01-21 18:31:04     BBB
2012-01-21 18:31:07     BBB
2012-01-21 18:31:10     BBB

События не сортируются по дате или пользователю.

Я хотел бы узнать минимальный интервал времени (в секундах) между двумя последовательными событиями для одного пользователя. Таким образом, результирующий набор будет выглядеть так:

MIN_INTERVAL        USER

3                   AAA
5                   BBB

Может ли кто-нибудь помочь мне придумать SQL-запрос, который генерирует это? Я не думаю, что GROUP BY поможет.

3 ответы

Этого можно добиться, сдвинув самосоединение на 1 запись (в порядке даты), которая получит время и его непосредственное предыдущее время в одну и ту же строку, чтобы мы могли сделать разницу в секундах между ними:

SELECT 
    a.user,
    MIN(TIMESTAMPDIFF(SECOND, b.date, a.date)) AS mindiff
FROM
(
    SELECT user, date, @val1:=@val1+1 AS rn
    FROM tbl
    CROSS JOIN (SELECT @val1:=0) AS val1_init
    ORDER BY date
) a
INNER JOIN
(
    SELECT user, date, @val2:=@val2+1 AS rn
    FROM tbl
    CROSS JOIN (SELECT @val2:=1) AS val2_init
    ORDER BY date
) b ON a.rn = b.rn
GROUP BY a.user

Демонстрация SQLFiddle


Промежуточные результаты (до GROUP BY)

Создан 20 июля ’12, 03:07

Простая версия может быть не самой быстрой?

SELECT t1.user, MIN(TIMESTAMPDIFF(SECOND, t1.date, t2.date))
FROM tbl AS t1
JOIN tbl AS t2 ON t1.user = t2.user
WHERE t1.date < t2.date
GROUP BY t1.user

Создан 20 июля ’12, 03:07

В mysql вам нужно сделать это, используя самосоединение и две группы:

select t.user, min(diff)
from (select t.user, unix_timestamp(tnext.date) - unix_timestamp(t.date) as diff
      from t join
           tnext
           on t.user = tnext.user and
              t.date < tnext.date
      group by t.user, t.date
     ) t
group by user

Внутренний подзапрос находит следующий раз и вычитает значения, чтобы получить разницу. Внешний возвращает наименьший diff.

Создан 20 июля ’12, 02:07

Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками

mysql
sql
timestamp

or задайте свой вопрос.

Есть таблица (Время, Цена, Объем)

Необходимо найти в заданном промежутке времени по определенному интервалу значения:

  • цена у минимального времени интервала, (не сделано)
  • цена у максимального времени интервала, (не сделано)

  • максимальная цена,

  • минимальная цена,
  • объем.

Что сделал: интервал в примере 3 дня, может быть хоть год или пару секунд и т.д.

SELECT 
    FLOOR(UNIX_TIMESTAMP(t1.TimeAdded)/(60 * 60 * 24 * 3)) AS timekey, 
    min(t1.TimeAdded), max(t1.TimeAdded),   
    min(t1.Price) as min_price, max(t1.Price) as max_price,
    SUM(t1.Quantity) as volume
FROM TradeFill as t1
WHERE t1.TimeAdded >= "2018-01-01 00:00:00" AND t1.TimeAdded <= "2018-08-10 23:59:59"
GROUP BY timekey;


SELECT VERSION()
5.5.56-MariaDB

CREATE TABLE `TradeFill` (
  `Id` bigint(20) NOT NULL AUTO_INCREMENT,
  `Price` decimal(32,20) NOT NULL,
  `Quantity` decimal(32,20) NOT NULL,
  `TimeAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=10370 DEFAULT CHARSET=utf8

Таблица

ID-----Price-----Quantity-----TimeAdded
1------2000------10-----------2018-08-09 00:01:00
2------5000------10-----------2018-08-09 00:02:00
3------1000------10-----------2018-08-09 00:03:00
4------7000------10-----------2018-08-09 00:05:00
5------3000------10-----------2018-08-09 00:04:00
6------2500------15-----------2018-08-10 00:00:00

Хочу видеть

min(t1.TimeAdded)-------max(t1.TimeAdded)-----PriceStart-----PriceFinish-----min_price-----max_price-----volume
2018-08-09 00:01:00-----2018-08-09 00:05:00---2000-----------3000------------1000----------7000----------50----
2018-08-10 00:00:00-----2018-08-10 00:00:00---2500-----------2500------------2500----------2500----------15----

Добавить комментарий