AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 76930264
Accepted
ALS
ALS
Asked: 2023-08-18 22:32:01 +0800 CST2023-08-18 22:32:01 +0800 CST 2023-08-18 22:32:01 +0800 CST

MySQL: Obter contagem de registros consecutivos (data)?

  • 772

Necessidade de obter a quantidade de dias que um usuário concluiu um hábito seguido (streak). Isso significa a sequência mais recente (hoje ao contrário) e não necessariamente a sequência mais longa.

Com as seguintes datas inseridas, estou esperando 4

  • 14/09/2023
  • 15/09/2023
  • 16/09/2023
  • 17/09/2023

Esta consulta está retornando 1 consistentemente, onde estou errando?

SELECT s.habit, MAX(s.streak) AS currentStreak
  FROM ( SELECT IF(@prev = o.habit_id AND o.date = @prevDate + INTERVAL 1 DAY
                  , @streak := @streak + 1
                  , @streak := 1
                ) AS streak
              , @prev := o.habit_id AS habit
           FROM ( SELECT t.habit_id
                       , DATE(t.created_at) AS `date`
                    FROM habit_progress_logs t
                   CROSS
                    JOIN (SELECT @prev := NULL, @prevDate := NULL, @streak := 1) i
                   GROUP BY t.habit_id, DATE(t.created_at)
                   ORDER BY t.habit_id, DATE(t.created_at)
                ) o
       ) s
  WHERE s.habit = 4
 GROUP BY s.habit

SQLFiddle com esquema e dados

mysql
  • 1 1 respostas
  • 53 Views

1 respostas

  • Voted
  1. Best Answer
    user1191247
    2023-08-19T01:05:26+08:002023-08-19T01:05:26+08:00

    Você esqueceu de definir @prevDatepara cada linha e está retornando a seqüência máxima em vez da seqüência mais recente.

    Se você estiver usando MySQL >= 8.0, poderá usar funções de janela , em vez da configuração obsoleta de variáveis ​​de usuário em expressões :

    WITH streaks AS (
        SELECT
            habit_id,
            DATE(created_at) AS dt,
            DATE(created_at) - INTERVAL DENSE_RANK() OVER (PARTITION BY habit_id ORDER BY DATE(created_at) ASC) DAY AS grp
        FROM habit_progress_logs
        WHERE habit_id = 4
    ),
    streaks2 AS (
        SELECT
            habit_id,
            grp,
            COUNT(DISTINCT dt) AS length,
            ROW_NUMBER() OVER (PARTITION BY habit_id ORDER BY grp DESC) AS rn
        FROM streaks
        GROUP BY habit_id, grp
    )
    SELECT habit_id, length AS currentStreak
    FROM streaks2
    WHERE rn = 1;
    

    O primeiro CTE nos dá o agrupamento da sequência de datas, usando DENSE_RANK() ( rnkadicionado para ilustração):

    habit_id dt rnk grp
    4 14/07/2023 1 13/07/2023
    4 15/07/2023 2 13/07/2023
    4 16/07/2023 3 13/07/2023
    4 17/07/2023 4 13/07/2023
    4 19/07/2023 5 14/07/2023
    4 2023-08-20 6 14/08/2023
    4 2023-08-21 7 14/08/2023
    4 2023-08-23 8 15/08/2023
    4 2023-08-24 9 15/08/2023
    4 2023-08-25 10 15/08/2023
    4 2023-08-26 11 15/08/2023
    4 2023-08-27 12 15/08/2023
    4 2023-08-28 13 15/08/2023
    4 13/09/2023 14 30/08/2023
    4 14/09/2023 15 30/08/2023
    4 15/09/2023 16 30/08/2023
    4 15/09/2023 16 30/08/2023
    4 16/09/2023 17 30/08/2023
    4 17/09/2023 18 30/08/2023

    A segunda CTE faz o GROUP BY e adiciona o ROW_NUMBER() :

    habit_id grp comprimento rn
    4 30/08/2023 5 1
    4 15/08/2023 6 2
    4 14/08/2023 2 3
    4 14/07/2023 1 4
    4 13/07/2023 4 5

    Se você está preso no MySQL < 8.0:

    SELECT habit_id, COUNT(*) AS currentStreak
    FROM (
      SELECT
        habit_id,
        dt,
        @grp := IF(@prevHabitId = habit_id AND dt = @prevDate + INTERVAL 1 DAY, @grp, @grp + 1) AS grp,
        @prevDate := dt,
        @prevHabitId := habit_id
      FROM (
        SELECT habit_id, DATE(created_at) AS dt
        FROM habit_progress_logs
        JOIN (SELECT @prevHabitId := NULL, @prevDate := NULL, @grp := 0) i
        WHERE habit_id = 4
        GROUP BY habit_id, dt
        ORDER BY habit_id, dt
      ) s
    ) t1
    GROUP BY habit_id, grp
    ORDER BY habit_id, grp DESC
    LIMIT 1;
    

    Aqui está um db<>fiddle

    • 1

relate perguntas

  • Wordpress - Biblioteca de Mídia - Sintaxe SQL

  • docker-compose: Não é possível conectar o serviço de aplicativo ao banco de dados mysql, recebo "Erro: acesso negado para o usuário 'root'@'localhost' (usando a senha: SIM)

  • MySQL Executar um script automático

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve