1
votes

Existe-t-il un moyen dans la requête SQL de classer une certaine valeur dans un ensemble ordonné d'enregistrements de sorte que le classement soit réinitialisé après avoir rencontré une valeur différente

Je veux classer la valeur "Lapsed" de l'indicateur de statut de telle manière qu'il se réinitialise après avoir rencontré une autre valeur et quand il rencontre à nouveau "Lapsed", il devrait recommencer le classement à partir de 1

je suis confus que comment pouvons-nous faire une telle chose dans SQL. J'ai essayé avec des fonctions analytiques mais pas de chance

Les données ressemblent à ceci.

id      yr_mon  status    lapsed_months
----------------------------------------
1002    201703  New            0
1002    201704  Retained       0
1002    201705  Unretained     0
1002    201706  Lapsed         1
1002    201707  Lapsed         2
1002    201708  Reactivated    0
1002    201709  lapsed         1
1002    201710  Unretained     0
1002    201711  Lapsed         1
1002    201712  Lapsed         2
1003    201703  New            0
1003    201704  Retained       0
1003    201705  Lapsed         1
1003    201706  Lapsed         2
1003    201707  Reactivated    0
1003    201708  Lapsed         1
1003    201709  Lapsed         2
1003    201710  Lapsed         3

La sortie devrait ressembler à ceci.

id      yr_mon  status
-------------------------
1002    201703  New
1002    201704  Retained
1002    201705  Unretained
1002    201706  Lapsed
1002    201707  Lapsed
1002    201708  Reactivated
1002    201709  lapsed
1002    201710  Unretained
1002    201711  Lapsed
1002    201712  Lapsed
1003    201703  New
1003    201704  Retained
1003    201705  Lapsed
1003    201706  Lapsed
1003    201707  Reactivated
1003    201708  Lapsed
1003    201709  Lapsed
1003    201710  Lapsed


0 commentaires

3 Réponses :


2
votes

Essayez de générer le RowNumber comme ci-dessous. Veuillez utiliser la commande appropriée des données selon les exigences.

id      yr_mon  Status      lapsed_months
1002    201703  New         0
1002    201704  Retained    0
1002    201705  Unretained  0
1002    201706  Lapsed      1
1002    201707  Lapsed      2
1002    201708  Reactivated 0
1002    201709  Retained    0
1002    201710  Unretained  0
1002    201711  Lapsed      1
1002    201712  Lapsed      2
1003    201801  New         0
1003    201802  Retained    0
1003    201803  Lapsed      1
1003    201804  Lapsed      2
1003    201710  Lapsed      3

La sortie peut être (mais, en l'absence de clause ORDER BY, non garantie):

SELECT * , @row_num :=IF(`status` = 'Lapsed',@row_num+1,0)AS RowNumber  
FROM 
(
    SELECT 1002 id,201703 yr_mon, 'New' `status` UNION ALL
    SELECT 1002,201704,'Retained' UNION ALL
    SELECT 1002,201705,'Unretained' UNION ALL
    SELECT 1002,201706,'Lapsed' UNION ALL
    SELECT 1002,201707,'Lapsed' UNION ALL
    SELECT 1002,201708,'Reactivated' UNION ALL
    SELECT 1002,201709,'Retained' UNION ALL
    SELECT 1002,201710,'Unretained' UNION ALL
    SELECT 1002,201711,'Lapsed' UNION ALL
    SELECT 1002,201712,'Lapsed' UNION ALL
    SELECT 1003,201801,'New' UNION ALL
    SELECT 1003,201802,'Retained' UNION ALL
    SELECT 1003,201803,'Lapsed' UNION ALL
    SELECT 1003,201804,'Lapsed' UNION ALL
    SELECT 1003,201710,'Lapsed'
)A


4 commentaires

Merci, pouvez-vous expliquer la syntaxe que vous avez utilisée


Une variable en ligne @row_num est utilisée et la valeur attribuée à cette variable compte tenu de la valeur de la colonne Status . Si la valeur est 'Lapsed', j'augmente simplement la valeur @row_num en définissant @row_num = @ row_num + 1 et pour toutes les autres valeurs, définissez @row_num = 0.


Puis-je demander, s'il vous plaît, quelle base de données cette requête est en cours d'exécution?


MySQL, comme vous l'avez marqué,



2
votes

Depuis la version 8.0, MySql prend en charge les fonctions de fenêtre. Groupez et numérotez les lignes dans un groupe

with grp as (
 select id, yr_mon, status
  , row_number() over(partition by id order by yr_mon) - row_number() over(partition by id, status order by yr_mon)  grp
 from tlog 
)
select id, yr_mon, status, case status when 'Lapsed' then row_number() over(partition by id, grp order by yr_mon) else 0 end lapsed_months
from grp
order by id, yr_mon; 

fiddle https: //dbfiddle.uk/?rdbms=mysql_8.0&fiddle=2d4fcfa5458096c0f3bf296099660d1c Notez que je place intentionnellement les données source dans un ordre arbitraire.


0 commentaires

0
votes

Vraisemblablement, vous voulez cela pour chaque id .

Vous voulez juste une somme cumulative des valeurs "caduques" . Vous pouvez exprimer cela dans MySQL 8+ comme suit:

select * ,
       (@rn := if(@id = id,
                  if(status = 'lapsed', @rn + 1, @rn),
                  0
                 )
       ) as lapsed_months
from (select t.*
      from t
      order by t.id, t.yr_mon
     ) t cross join
     (select @i := -1, @rn := 1) params;

Dans les versions antérieures, vous pouvez utiliser des variables comme celle-ci:

select l.*,
       sum(status = 'lapsed') over (partition by id order by yr_mon) as lapsed_months
from t;

p>


0 commentaires