2014-01-31 4 views
2

У меня есть столбец значений DATETIME в MySQL, и я хочу вернуть наименьшую разницу между любыми двумя из этих значений в столбце; Мне не нужно знать, какими значениями была разница между ними или когда она была, просто разница между этими двумя значениями одна.Как определить разницу между значениями в столбце базы данных и вернуть наименьшую разницу?

Мой стол выглядит примерно так.

id | launch_date_time 
---------------------------- 
1  | 2012-01-02 18:42:00 
2  | 2012-04-05 07:23:50 
... 
x  | 2014-08-07 22:19:11 

Может кто-нибудь сможет указать мне правильное направление для построения такого запроса?

+0

Cant вы делаете это на своем интерфейсе? как php, python, ...? – Melon

+0

Я мог бы, используя PHP. Какой был бы лучший способ сделать это ... foreach loop? – ReactingToAngularVues

+0

Я думаю, что это будет сложно сделать с запросом (но вы можете использовать функцию БД). Если это небольшой набор данных, я бы экспортировал его в excel, сортировал его и использовал формулу для вычисления различий и сортировки - 5 минут работы. Если это большой набор данных, и вам нужно будет делать это на регулярной основе, лучше создайте триггер на INSERT, который вычисляет разницу между now() и последним INSERT и сохраняет его в «diff-table». – alfasin

ответ

0
select id,FROM_UNIXTIME(launch_date_time) as uTime,max(FROM_UNIXTIME(launch_date_time)) as max from table; 

//do db stuff 
    //set the lowest to highest possible number so first comparison it will become the lowest. 

    $lowest = $result['max']; 

// iterate through array to get each time 
foreach ($result['uTime'] as $v) 
{ 

//iterate again to compare each time u got from first loop to each in this loop 

    foreach ($result['uTime as $x) 
    { 
//subtract your first value from the current 
     $diff = $v - $x; 

//if its lower then any previous, and its positive set the new lowest. 
     if ($diff < $lowest and $diff > 0) 
     { 
      $lowest = $diff; 
     } 
    } 
} 
echo $lowest; 

нету испытал это ....

1

Моя первая идея состоит в том, если имя таблицы table это сделать

select min(abs(datediff(t1.launch_date_time, t2.launch_date_time))) 
    from table t1 
    , table t2 
where t1.id <> t2.id 

это зависит, насколько велика эти таблицы, выше O (N^2) в O (N * log N), вы можете сделать это путем сортировки, а результат - min последовательных элементов

// pseudo code 
list = fromDb(); 
sort(list); 
min = list[1] - list[0]; 
for i in 2 to list.size() 
    min = min(min, list[i] - list[i-1]) 
+1

Если записи одинаково упорядочены как «id», так и «launch_date_time», а в «id» нет отверстий, то этого может быть достаточно для самосоединения на t1.id = t2.id + 1, который имеет O (n) сложности. – Bronx

+0

Правильно, но только ОП знает, что это ... Я не совсем уверен, что это O (n), это зависит от внутренней реализации. Для простого для каждого id найдите id + 1 в log (n) - проиндексированном, он все еще O (N * log N), если индекс является деревом, все еще можно реализовать как обход дерева ... – Betlista

0

Попробуйте этот запрос -

SELECT 
    t1.launch_date_time, MIN(t2.launch_date_time) launch_date_time2 
FROM launch t1 
    JOIN launch t2 
    ON t2.launch_date_time > t1.launch_date_time 
GROUP BY 
    t1.launch_date_time 
ORDER BY 
    DATE(MIN(t2.launch_date_time)) * 86400 + TIME_TO_SEC(TIME(MIN(t2.launch_date_time))) - DATE(t1.launch_date_time) * 86400 + TIME_TO_SEC(TIME(t1.launch_date_time)) 
LIMIT 1 
+0

Я не совсем уверен о производительности этого запроса ... Присоединяйтесь к 'launch_date_time'? Вам не нужно 'abs', просто вычитайте t2 время с t1, когда в join есть' t2.launch_date_time> t1.launch_date_time' ... – Betlista

+0

INDEX (launch_date_time) поможет оптимизировать объединение таблиц. ABS - я изменил запрос. – Devart

0

метод SQL сделать это в одном операторе (разница здесь в днях): -

SELECT MIN(DATEDIFF(Sub1.launch_date_time, Sub2.launch_date_time)) 
FROM 
(
    SELECT id, launch_date_time, @aCnt1 := @aCnt1 + 1 AS SeqCnt 
    FROM SomeTable 
    CROSS JOIN 
    (
     SELECT @aCnt1:=0 
    ) Deriv1 
    ORDER BY launch_date_time 
) Sub1 
INNER JOIN 
(
    SELECT id, launch_date_time, @aCnt2 := @aCnt2 + 1 AS SeqCnt 
    FROM SomeTable 
    CROSS JOIN 
    (
     SELECT @aCnt2:=1 
    ) Deriv2 
    ORDER BY launch_date_time 
) Sub2 
ON Sub1.SeqCnt = Sub2.SeqCnt 

SQL скрипку здесь: -

http://www.sqlfiddle.com/#!2/6dc399/1

Смежные вопросы