MySQL подсчитывать дни подряд / дни подряд - PullRequest
0 голосов
/ 07 августа 2020

У меня две таблицы. Оба содержат записи одного пользователя, один с утра, один с вечера.

Я пытаюсь получить количество дней, в которые пользователь, следовательно, добавил одну запись утром И еще одну вечером. Всякий раз, когда один отсутствует, «полоса» заканчивается - заканчиваясь в текущий день. Так что не имеет значения, что пользователь был активен год a go и имел 100 дней подряд, это просто «сколько дней подряд пользователь добавил запись в утреннюю таблицу, а также в вечернюю таблицу. , возвращаясь с сегодняшнего дня ».

В обеих таблицах есть временные метки каждой записи.

Пример:

morningTable:

ID text timestamp
1  bla  2020-08-07 10:30:00
2  blub 2020-08-06 11:30:00
3  abc  2020-08-05 09:20:00
4  def  2020-08-04 06:13:00
5  ghi  2020-08-02 07:05:00

eveningTable:

ID text timestamp
1  abc  2020-08-07 19:30:00
2  def  2020-08-06 20:45:00
3  ghi  2020-08-05 21:30:00
4  jkl  2020-08-03 20:13:00
5  mno  2020-08-01 17:33:00
6  pqr  2020-07-29 19:19:19

Таким образом, с этими двумя таблицами результат должен быть будет числом 3, так как в обеих таблицах есть 05.08 - 07.08 подряд ...

Надеюсь, вы понимаете мой случай.

Я нашел примеры с ROWNUMBER, чтобы найти пробелы et c, однако его сложно объединить с обеими таблицами.

Может ли кто-нибудь помочь мне, как это сделать с MySQL?

Я также думаю о том, чтобы просто собрать все данные в PHP и делать это там, однако, когда объем данных растет, будет намного более производительно делать это с MySQL (сторона базы данных), а не с PHP.

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 07 августа 2020

Объедините таблицы, используя union all, и объедините, чтобы получить дни с и . Затем используйте методы пробелов и островов:

with me as (
      select dte
      from ((select date(timestamp) as dte, 1 as morning, 0 as evening
             from morning
            ) union all
            (select date(timestamp) as dte, 0 as morning, 1 as evening
             from evening
            )
           ) me
      group by dte
      having sum(morning) > 0 and sum(evening) > 0
     )
select min(dte), max(dte), count(*)
from (select dte, row_number() over (order by dte) as seqnum
      from me
     ) me
group by dte - interval seqnum day
order by count(*) desc
limit 1;

Здесь - скрипт db <>.

EDIT:

Фактически, это не особо сложно адаптировать переменные к этой задаче:

select min(dte), max(dte), count(*)
from (select dte, (@rn := @rn + 1) as seqnum
      from (select dte
            from ((select date(timestamp) as dte, 1 as morning, 0 as evening
                   from morning
                  ) union all
                  (select date(timestamp) as dte, 0 as morning, 1 as evening
                   from evening
                  )
                 ) me
            group by dte
            having sum(morning) > 0 and sum(evening) > 0
            order by dte
           ) d cross join
           (select @rn := 0) params
     ) me
group by dte - interval seqnum day
order by count(*) desc
limit 1;
1 голос
/ 07 августа 2020
WITH 
cte1 AS ( SELECT DISTINCT DATE(m.`timestamp`) uni_date                              
          FROM morningTable m
          JOIN eveningTable e ON DATE(m.`timestamp`) = DATE(e.`timestamp`) ),
cte2 AS ( SELECT uni_date, ROW_NUMBER() OVER (ORDER BY uni_date DESC) rn
          FROM cte1 )
SELECT MAX(DATEDIFF( CURRENT_DATE, uni_date ) + 1) output
FROM cte2
WHERE rn = DATEDIFF( CURRENT_DATE, uni_date ) + 1

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

PS. Извините, это доступно, начиная с MariaDB 10.2.1 ...

В MariaDB 10.1.45 следующий запрос должен работать:

SELECT DATEDIFF(CURRENT_DATE, MIN(uni_date)) + 1 output
FROM ( SELECT DISTINCT DATE(m.`timestamp`) uni_date                              
       FROM morningTable m
       JOIN eveningTable e ON DATE(m.`timestamp`) = DATE(e.`timestamp`) ) t1
WHERE NOT EXISTS ( SELECT NULL
                   FROM ( SELECT DISTINCT DATE(m.`timestamp`) uni_date                              
                          FROM morningTable m
                          JOIN eveningTable e ON DATE(m.`timestamp`) = DATE(e.`timestamp`) ) t2
                   WHERE t2.uni_date = t1.uni_date - INTERVAL 1 DAY )
  AND ( SELECT DATE(MAX(m.`timestamp`))
        FROM morningTable m
        JOIN eveningTable e ON DATE(m.`timestamp`) = DATE(e.`timestamp`) ) = CURRENT_DATE

Если сегодня нет строки хотя бы в одной таблице, запрос вернет NULL - вместо этого вы можете использовать COALESCE для получения нуля.

...