2016-06-02 2 views
2

Je souhaite classer une valeur nulle consécutive pour mes enregistrements. Chaque enregistrement sera classé comme 1. Pour la valeur nulle qui n'apparaît qu'une seule fois, le rang sera également 1. Mais pour les valeurs nulles qui apparaissent de façon consécutive, le rang sera 1 pour le premier enregistrement et 2 pour le second. enregistrer et ainsi de suite. Voici mon code.Classement des valeurs nulles consécutives

CREATE TABLE #my_table 
(
    id BIGINT      IDENTITY PRIMARY KEY 
    ,fruit       varchar(100) 
); 

INSERT INTO #my_table 
      SELECT 'apple' 
UNION ALL SELECT 'apple' 
UNION ALL SELECT NULL 
UNION ALL SELECT 'pineapple' 
UNION ALL SELECT 'banana' 
UNION ALL SELECT NULL 
UNION ALL SELECT NULL 
UNION ALL SELECT 'orange' 

select * from #my_table 

Résultat recherché

+----+-----------+------+ 
| id | fruit  | rank | 
+----+-----------+------+ 
| 1 | apple  | 1 | 
| 2 | apple  | 1 | 
| 3 | NULL  | 1 | 
| 4 | pineapple | 1 | 
| 5 | banana | 1 | 
| 6 | NULL  | 1 | 
| 7 | NULL  | 2 | 
| 8 | orange | 1 | 
+----+-----------+------+ 

Comment dois-je l'interroger?

Aidez s'il vous plaît!

+0

Quelle est la version SQL Server? –

+0

Salut! Son serveur SQL 2014 – eric

Répondre

1

Vous pouvez utiliser la différence de ROW_NUMBER pour obtenir le regroupement des valeurs NULL consécutives:

WITH Cte AS(
    SELECT *, 
     g = ROW_NUMBER() OVER(ORDER BY id) 
       - ROW_NUMBER() OVER(PARTITION BY fruit ORDER BY id) 
    FROM #my_table 
) 
SELECT 
    id, 
    fruit, 
    CASE 
     WHEN fruit IS NULL THEN ROW_NUMBER() OVER(PARTITION BY fruit, g ORDER BY id) 
     ELSE 1 
    END AS rank 
FROM Cte 
ORDER BY id; 

ONLINE DEMO

1
CREATE TABLE #my_table 
(
    id BIGINT      IDENTITY PRIMARY KEY 
    ,fruit       varchar(100) 
); 

INSERT INTO #my_table 
      SELECT 'apple' 
UNION ALL SELECT 'apple' 
UNION ALL SELECT NULL 
UNION ALL SELECT 'pineapple' 
UNION ALL SELECT 'banana' 
UNION ALL SELECT NULL 
UNION ALL SELECT NULL 
UNION ALL SELECT 'orange' 

; 
WITH REC_CTE (id,fruit,ranks) 
    AS (
     -- Anchor definition 
     SELECT id, 
       fruit, 
       1 as ranks 
     FROM #my_table 
     WHERE fruit is not null 

      -- Recursive definition 
     UNION ALL 
     SELECT son.id, 
       son.fruit, 
       case when son.fruit is null AND father.fruit is null then 
        father.ranks + 1 
        else 
        1 
       end as ranks 
     FROM #my_table son INNER JOIN 
       REC_CTE father 
     on son.id = father.id +1 
     WHERE son.fruit is null 
      --AND father.fruit is null 
    ) 

    SELECT * from REC_CTE order by id 

    DROP TABLE #my_table 
0

solution suivante n'utilise pas récursion (limité à 32767 niveau = ~ lignes en fonction de la solution) et aussi il utilise seulement deux fonctions d'agrégation/classement (SUM et DENSE_RANK):

;WITH Base 
AS (
    SELECT *, IIF(fruit IS NULL, SUM(IIF(fruit IS NOT NULL, 1, 0)) OVER(ORDER BY id), NULL) AS group_num 
    FROM @my_table t 
) 
SELECT *, IIF(fruit IS NULL, DENSE_RANK() OVER(PARTITION BY group_num ORDER BY id), 1) rnk 
FROM Base b 
ORDER BY id 

Résultats:

id fruit  group_num rnk 
--- --------- --------- --- 
100 apple  NULL  1 
125 apple  NULL  1 
150 NULL  2   1 
175 pineapple NULL  1 
200 banana NULL  1 
225 NULL  4   1 
250 NULL  4   2 
275 orange NULL  1 
300 NULL  5   1 
325 NULL  5   2 
350 NULL  5   3