6 votes

Répétition de la valeur entre deux valeurs d'une colonne

J'essaie de répéter la première valeur spécifique non vide dans une colonne jusqu'à la prochaine valeur spécifique non vide dans la même colonne. Comment faire ?

Les données se présentent comme suit :

ID | Msg  
---+-----
 1 |     
 2 |  
 3 |  
 4 |  
 5 | Beg  
 6 | End  
 7 |  
 8 | Beg  
 9 |  
10 |   
11 |  
12 | End

Il devrait en être ainsi :

ID | Msg  
---+-----
 1 |     
 2 |  
 3 |  
 4 |  
 5 | Beg  
 6 | End  
 7 |  
 8 | Beg    
 9 | Beg   
10 | Beg    
11 | Beg  
12 | End

J'ai regardé dans LAG() y LEAD() mais je continue à penser que je devrais utiliser un CURSOR pour cela. J'en ai entendu parler, mais je ne les ai pas encore utilisés dans ce cas.

6voto

John Cappelletti Points 43460

Une autre option consiste à utiliser un drapeau et un sum() over

Exemple

Select ID
      ,Msg = case when sum( case when [Msg]='Beg' then  1 when [Msg]='End' then -1  else 0 end ) over (order by ID) = 1 and Msg='' then 'Beg' else Msg end
 From  YourTable

Retours

ID  Msg
1   
2   
3   
4   
5   Beg
6   End
7   
8   Beg
9   Beg
10  Beg
11  Beg
12  End

4voto

Samir Points 275

Puisque vous utilisez MSSQL, vous pouvez écrire un CTE pour obtenir le résultat que vous recherchez.

Essayez ce CTE :

declare @tab table
(
    id int,
    msg char(3)
)

insert into @tab
values  
(1, ''),
(2, ''),   
(3, ''),   
(4, ''),   
(5, 'Beg'),   
(6, 'End'),   
(7, ''),   
(8, 'Beg'),   
(9, ''),   
(10, ''),
(11, ''),   
(12, 'End')

;with cte as
(
    select top 1 tab.id, tab.msg
    from @tab tab
    order by tab.id

    union all

    select tab.id, case when tab.msg = '' and cte.msg = 'beg' then cte.msg else tab.msg end
    from @tab tab
    inner join cte cte on cte.id + 1 = tab.id
)

select *
from cte

3voto

Mike Points 943

Données

DECLARE @id AS TABLE (
    ID INT
,   MSG VARCHAR(3)
)

INSERT INTO @ID (ID, MSG)
SELECT 1, ''
UNION
SELECT 2, ''
UNION
SELECT 3, ''
UNION
SELECT 4, ''
UNION
SELECT 5, 'Beg'
UNION
SELECT 6, 'End'
UNION
SELECT 7, ''
UNION
SELECT 8, 'Beg'
UNION
SELECT 9, ''
UNION
SELECT 10, ''
UNION
SELECT 11, ''
UNION
SELECT 12, 'End'

Demande de renseignements

SELECT 
    final.id 
,   CASE 
        WHEN msg = '' AND C.begCount>c.EndCount THEN 'Beg' 
        ELSE final.MSG
    END Msg
FROM @id final
INNER JOIN 
(
SELECT ID
,   (SELECT COUNT(*) FROM @ID B WHERE B.ID < MAIN.ID AND MSG ='BEG') begCount
,   (SELECT COUNT(*) FROM @ID B WHERE B.ID < MAIN.ID AND MSG ='END') EndCount 
FROM @id MAIN
) C
ON C.ID = final.ID

3voto

Alex Sham Points 452

Voici un fichier SQL sans jointures automatiques - utilisant uniquement les fonctions de la fenêtre

select
     dat.id, 
     isnull(nullif(max(dat.msg) over (partition by dat.gr), 'End'), dat.msg) as msg
from (
    select
         dat.id,
         dat.msg,
         dat.wind + sum(dat.is_end) over (order by dat.id) as gr
    from (
        select
             t.id, 
             t.msg,
             sum(iif(t.msg = 'Beg' ,1,0)) over (order by t.id) as wind,
             iif (t.msg = 'End', 1, 0) as is_end
        from t
    ) dat
) dat

1voto

Aura Points 1135

Vous pouvez essayer le code suivant, il fonctionnera pour le cas que vous avez demandé mais il n'est pas sûr qu'il fonctionnera pour tous les autres cas puisque l'énoncé du cas est spécifique au positionnement décrit ci-dessus :

WITH cte AS(
SELECT *, LEAD(Msg, 1, 0) OVER (ORDER BY ID) AS leadval, LAG(Msg, 1, 0) OVER (ORDER BY ID) AS lagval
FROM msg),
cte2 AS(
SELECT cte.ID,
       cte.Msg,
       cte.leadval,
       cte.lagval,
       CASE WHEN cte.Msg = 'Beg' THEN 'Beg'
       WHEN cte.Msg = '' AND cte.leadval = '' AND cte.lagval = 'Beg' THEN 'Beg'
       WHEN cte.Msg = '' AND cte.leadval = 'END' THEN 'Beg'
       ELSE cte.Msg end AS Msg2
FROM cte), cte3 AS(
SELECT *, LEAD(cte2.Msg2, 1, 0) OVER (ORDER BY cte2.ID) AS 'LeadVal2'
FROM cte2)
SELECT ID, CASE WHEN cte3.Msg2 = '' AND cte3.LeadVal2 = 'Beg' AND cte3.leadval <> 'Beg' THEN 'Beg' ELSE cte3.Msg2 END AS msg
FROM cte3

Sortie :

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X