2014-01-20 2 views
1

У меня есть таблица MySQL следующего видаТрудно MySQL Query - Получение разницы Макс между датами

account_id | call_date 
1   2013-06-07 
1   2013-06-09 
1   2013-06-21 
2   2012-05-01 
2   2012-05-02 
2   2012-05-06 

Я хочу написать запрос MySQL, который будет получать максимальную разницу (в днях) между последовательными датами в call_date для каждого account_id. Таким образом, для приведенного выше примера результатом этого запроса будет

account_id | max_diff 
1   12 
2   4 

Я не уверен, как это сделать. Возможно ли это сделать в запросе MySQL?

Я могу сделать datediff(max(call_date),min(call_date)), но это будет игнорировать даты между первой и последней датами вызова. Мне нужно каким-то образом получить datediff() между каждым последующим call_date для каждого account_id, а затем найти максимум из них.

+0

Я не уверен, что это будет возможно сделать с помощью одного запроса. –

+1

Вы что-то пробовали? Пожалуйста, прочитайте [эту статью] (http://whathaveyoutried.com). Максимальная разница - это разница между минимальным и максимальным значениями даты, не так ли? Подсказки: используйте агрегированные функции 'min()' и 'max()' и используйте 'date_diff()'. – Barranka

+0

Пожалуйста, покажите свою работу. – Strawberry

ответ

0
SELECT a1.account_id , max(a1.call_date - a2.call_date) 
FROM account a2, account a1 
WHERE a1.account_id = a2.account_id 
AND a1.call_date > a2.call_date 
AND NOT EXISTS 
    (SELECT 1 FROM account a3 WHERE a1.call_date > a3.call_date AND a2.call_date < a3.call_date) 
GROUP BY a1.account_id 

Что дает:

ACCOUNT_ID MAX(A1.CALL_DATE - A2.CALL_DATE) 
1   12 
2   4 
+0

Я думаю, что @fancypants правильно интерпретирует требования OP - хотя я согласен, что это было немного расплывчато. – Strawberry

+0

@ Strawberry oh я вижу .. –

+0

Я имел в виду максимальную разницу между датами SUCCESSIVE. извините, если неясны. – user1893354

1
CREATE TABLE t 
    (`account_id` int, `call_date` date) 
; 

INSERT INTO t 
    (`account_id`, `call_date`) 
VALUES 
    (1, '2013-06-07'), 
    (1, '2013-06-09'), 
    (1, '2013-06-21'), 
    (2, '2012-05-01'), 
    (2, '2012-05-02'), 
    (2, '2012-05-06') 
; 

select account_id, max(diff) from (
select 
account_id, 
timestampdiff(day, coalesce(@prev, call_date), call_date) diff, 
@prev := call_date 
from 
t 
, (select @prev:=null) v 
order by account_id, call_date 
) sq 
group by account_id 

| ACCOUNT_ID | MAX(DIFF) | 
|------------|-----------| 
|   1 |  12 | 
|   2 |   4 | 
  • увидеть его работы вживую в sqlfiddle
+0

Я получаю сообщение 'Функция 'set_user_var' может использоваться только в крайнем выборе select или order by и не может использоваться в сочетании с функцией агрегата.' – user1893354

+0

Это а не сообщение об ошибке из MySQL напрямую, но я бы поспорил, что вы можете обойти его, выпустив 'set @prev = null;' перед запуском запроса и удалив ', (select @prev: = null) v' after' from' в выборе. – fancyPants

+0

Это проблема с используемой мной БД? – user1893354

0

Если у вас есть индекс по account_id, call_date, то вы можете сделать это достаточно эффективно без переменных:

select account_id, max(call_date - prev_call_date) as diff 
from (select t.*, 
      (select t2.call_date 
       from table t2 
       where t2.account_id = t.account_id and t2.call_date < t.call_date 
       order by t2.call_date desc 
       limit 1 
      ) as prev_call_date 
     from table t 
    ) t 
group by account_id; 
2

Я уверен, что ответ FP будет быстрее, но просто для удовольствия ...

SELECT account_id 
    , MAX(diff) max_diff 
    FROM 
    (SELECT x.account_id 
      , DATEDIFF(MIN(y.call_date),x.call_date) diff 
     FROM my_table x 
     JOIN my_table y 
      ON y.account_id = x.account_id 
      AND y.call_date > x.call_date 
     GROUP 
      BY x.account_id 
      , x.call_date 
    ) z 
GROUP 
    BY account_id; 
0

Только для образовательных целей, делая это с JOIN:

SELECT t1.account_id, 
    MAX(DATEDIFF(t2.call_date, t1.call_date)) AS max_diff 
FROM t t1 
LEFT JOIN t t2 
ON t2.account_id = t1.account_id 
    AND t2.call_date > t1.call_date 
LEFT JOIN t t3 
ON t3.account_id = t1.account_id 
    AND t3.call_date > t1.call_date 
    AND t3.call_date < t2.call_date 
WHERE t3.account_id IS NULL 
GROUP BY t1.account_id 

Поскольку вы Бесполезный 't указать, это показывает max_diff из NULL для счетов только с одним вызовом.

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