Получить уникальные данные из базы данных, ближайшей к выбранной дате - PullRequest
0 голосов
/ 02 сентября 2018

Я хочу получить данные, наиболее близкие к определенной дате, в прошлом или будущем, в зависимости от того, что ближе к дате. Но мне также нужно, чтобы оно было distinct по type. Например:

id |type |data | date                
 1 |0    |1904 |2018-08-19 00:14:32
 2 |0    |1904 |2018-08-19 00:24:47
 3 |0    |1904 |2018-08-19 05:02:30
 4 |0    |1904 |2018-08-22 00:05:58
 5 |0    |1904 |2018-08-22 00:08:34
 6 |4    |1903 |2018-08-19 00:14:31
 7 |6    |1926 |2018-08-19 00:14:32
 8 |6    |1926 |2018-08-19 04:44:10
 9 |6    |1926 |2018-08-19 04:52:58
10 |6    |1926 |2018-08-19 04:59:23
11 |6    |1926 |2018-08-22 00:05:58
12 |6    |1926 |2018-08-22 00:07:52
13 |6    |1926 |2018-08-22 00:08:34
14 |7    |1564 |2018-08-19 00:14:32
15 |8    |1900 |2018-08-19 00:14:32 

Если я укажу дату и время: 2018-08-19 00:00:00. Я должен получить следующие результаты:

id | type
 1 | 0    
 6 | 4
 7 | 6
14 | 7
15 | 8

Или, если я укажу дату и время: 2018-09-03 00:00:00. Я ожидаю:

id | type
 5 | 0    
 6 | 4
13 | 6
14 | 7
15 | 8

Или, наконец: 2018-08-22 00:05:58.

id | type
 4 | 0    
 6 | 4
11 | 6
14 | 7
15 | 8

Я пробовал несколько запросов, которые на самом деле не имели смысла ... Например:

SELECT *
FROM history 
WHERE (ABS(TIMESTAMPDIFF(DAY, date, "2018-08-19 00:08:34")) < 4) AND user_id = 1299
GROUP BY type
ORDER BY date

В любом случае, возможно ли это только с помощью запроса MySQL? Нужно ли использовать какую-то логику приложения для этого? Как мне запросить это?

SQL скрипка

Ответы [ 4 ]

0 голосов
/ 02 сентября 2018

это должно сработать.

create table test2 as
select c.id,c.type from(
select a.*,b.min
from test as a
left join
(select id, min(abs(date-"2018-09-01 00:00:00"dt)) as min from test
group by type ) as b
on a.id = b.id
) as c
where min = abs(date-"2018-09-01 00:00:00"dt)
order by id;

мы оставили соединение по id обратно в исходную таблицу min abs datediff, затем мы выбираем нужные записи.

0 голосов
/ 02 сентября 2018

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

Во-первых, вам нужен совокупный подзапрос, чтобы получить предельное значение: минимальное время разницы между строками каждого типа и вашей целевой датой. (http://sqlfiddle.com/#!9/b51a7a/26/1)

      SET @target := '2018-08-20 00:00:00';
      SELECT type, MIN(ABS(TIMESTAMPDIFF(MINUTE, date, @target))) delta
        FROM history
       GROUP BY type

Затем вы присоединяете это к исходной таблице, используя предложение ON для соответствия как типу, так и времени дельта. Собираем все вместе (http://sqlfiddle.com/#!9/b51a7a/27/1)

SET @target := '2018-08-20 00:00:00';
SELECT history.*
  FROM history
  JOIN (
          SELECT type, MIN(ABS(TIMESTAMPDIFF(MINUTE, date, @target))) delta
            FROM history
           GROUP BY type
      ) delta ON history.type=delta.type 
              AND ABS(TIMESTAMPDIFF(MINUTE, date, @target)) = delta

Редактировать проще получить только ближайший будущий или ближайший прошедший элемент к дате. Подзапрос (для ближайшего прошлого):

         SELECT type, MAX(date) date
           FROM history
         WHERE date <= @target
         GROUP BY date

Тогда общий запрос

  SELECT history.*
    FROM history
    JOIN (
             SELECT type, MAX(date) date
               FROM history
             WHERE date <= @target
             GROUP BY date
         ) m ON history.type = m.type AND history.date = m.date 
0 голосов
/ 02 сентября 2018

Вы можете легко сделать это, имитируя функцию row_number() из других СУБД, упорядочивая по abs(timestampdiff(second, date, @dt)):

select @rn := 0, @dt := cast('2018-08-19 04:52:00' as datetime);
select id, type from (
    select id,
           type,
           data,
           date,
           @rn := @rn + 1 rn
    from history
    order by abs(timestampdiff(second, date, @dt))
) a where rn = 1;

DEMO

0 голосов
/ 02 сентября 2018

Вы можете использовать внутреннее соединение в подзапросе для min diff

select 
    h.id, h.type 
from 
    history  
inner join  
    (select
         type, min(TIMESTAMPDIFF(SECOND, date, '2012-06-06 15:20:18')) min_diff 
     from  
         history
     where
         (abs(TIMESTAMPDIFF(DAY, date, "2018-08-19 00:08:34")) < 4) 
         and user_id = 1299
     group by  
         type) t on t.type = h.type 
                 and TIMESTAMPDIFF(SECOND, h.date, '2012-06-06 15:20:18') = t.min_diff
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...