2017-09-11 5 views
1

Je vise à obtenir un record établi comme celui-cipartitions de numérotation progressive T-SQL

date flag number 
01  0  1 
02  0  1 
03  1  2 
04  1  2 
05  1  2 
06  0  3 
07  1  4 
08  1  4 

Je pars du record avec « date » et « drapeau » seulement. J'essaie de calculer la colonne "nombre" en utilisant les fonctions de classement et de partitionnement T-SQL.

Un classement normale donnerait un résultat comme celui-ci:

date flag number 
    01  0  1 
    02  0  1 
    03  1  2 
    04  1  2 
    05  1  2 
    06  0  1 
    07  1  2 
    08  1  2 

Toute suggestion?

Répondre

1

Vous pouvez essayer ceci:

DECLARE @DataSource TABLE 
(
    [date] CHAR(2) 
    ,[flag] BIT 
); 

INSERT INTO @DataSource ([date], [flag]) 
VALUES ('01', 0) 
     ,('02', 0) 
     ,('03', 1) 
     ,('04', 1) 
     ,('05', 1) 
     ,('06', 0) 
     ,('07', 1) 
     ,('08', 1); 

WITH DataSource ([date], [flag], [number]) AS 
(
    SELECT [date] 
      ,[flag] 
      ,IIF(LAG([flag], 1, NULL) OVER (ORDER BY [date]) = [flag], 0, 1) 
    FROM @DataSource 
) 
SELECT [date] 
     ,[flag] 
     ,SUM([number]) OVER (ORDER BY [date] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [number] 
FROM DataSource 
ORDER BY [date], [flag]; 

enter image description here

L'idée est de vérifier si le groupe est modifié en utilisant la fonction LAG:

IIF(LAG([flag], 1, NULL) OVER (ORDER BY [date]) = [flag], 0, 1) 

Puis, en utilisant le BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW à SUM groupe changements.

1

j,

SQL Server 2012 a un certain nombre de nouvelles fonctions par exemple SQL Lead() et fonctions Lag SQL(). Vous pouvez utiliser le SQL Server Lag() function pour la solution de vos besoins

Voici ma solution

with cte as (
select 
    date, flag, 
    LAG(flag, 1, NULL) OVER (ORDER BY date) AS preVal, 
    case when flag = ISNULL((LAG(flag, 1, NULL) OVER (ORDER BY date)), flag) then 0 else 1 end as i 
from recordset 
) 
select 
    cte.date, 
    cte.flag, 
    sum(cte2.i)+1 r 
from cte 
inner join cte as cte2 on cte.date >= cte2.date 
group by cte.date, cte.flag 
order by cte.date 
+0

votre solution est bonne et le travail, merci toi. Je préférais gotqn car il est plus linéaire donc lisible, et il utilise la clause rows/range option de la commande OVER BY. –

+1

pas de problème :) J'ai aussi appris l'option "ENTRE NOBLES PRÉCÉDENTS ET LIGNE COURANTE" qui est mieux de continuer avec – Eralper

0

Vous pouvez alimenter dans un curseur comme celui-ci:

DECLARE @Table TABLE (
[Date] [nvarchar](50) NULL, 
[flag] [int] NULL, 
[Number] [int] NULL 
) 

DECLARE @Date nvarchar(50) 
DECLARE @flag int 
DECLARE @number int 
DECLARE @flagnumber int 
DECLARE @flagincrement int 

DECLARE MyCursor CURSOR FOR 
SELECT [Date],FLag 
FROM [LegOgSpass].[dbo].[testflag] 
Order by [Date] 

OPEN MyCursor 
FETCH NEXT FROM MyCursor 
INTO @Date,@flag 

IF (@@FETCH_STATUS>=0) 
BEGIN 

SET @number = 1 
SET @flagincrement = @flag 

INSERT INTO @Table ([Date],[Flag],[Number]) 
VALUES(@Date,@flag,@number) 

FETCH NEXT FROM MyCursor INTO @Date,@flag 
END 
WHILE (@@FETCH_STATUS<>-1) 
BEGIN 
IF (@@FETCH_STATUS<>-2) 
IF @flagincrement = @flag 
SET @number = @number 

ELSE 
SET @number = @number+1 
SET @flagincrement = @flag 

INSERT INTO @Table ([Date],[Flag],[Number]) 
VALUES(@Date,@flag,@number) 
FETCH NEXT FROM MyCursor INTO @Date,@flag 
END 

CLOSE MyCursor 
DEALLOCATE MyCursor 

SELECT * FROM @Table 
+0

Votre solution est acceptable, merci, mais j'essaie d'éviter les curseurs et les itérations: Je suis en train de mettre à jour la question. –

+0

Je sais, je voulais juste donner un exemple- Heureux que tu l'aies au travail :) – plaidDK