2016-10-14 1 views
2

J'ai besoin de remplir/remplacer les lignes avec '-' entre deux 'AL' OU deux 'MX' avec la valeur 'AL' ou 'MX' selon l'endroit où le '-' apparaît. Dans le but de cet exemple, j'utilise seulement 2 'uid' (j'ai en fait plus d'uid). En outre, la table est ordonnée par colonne uid et code_date dans ASCSQL: Comment remplir les lignes entre 2 lignes spécifiques avec la même valeur?

Pour faciliter la compréhension, j'ai ce tableau:

enter image description here

mais j'aimerai avoir quelque chose comme ceci:

enter image description here J'utilise SQL Server 2008. Toute suggestion sur la façon dont je peux y parvenir ???

J'ai créé la table avec le code suivant:

DECLARE @Customers TABLE 
    (uid bigint, 
    code_date date, 
    Value nchar(10) 
    ) 

INSERT INTO @Customers 
VALUES (1591, '2016-08-01', ''), 
    (1591, '2016-08-02', ''), 
    (1591, '2016-08-03', 'AL'), 
    (1591, '2016-08-04', '-'), 
    (1591, '2016-08-05', '-'), 
    (1591, '2016-08-06', '-'), 
    (1591, '2016-08-07', '-'), 
    (1591, '2016-08-08', '-'), 
    (1591, '2016-08-09', 'AL'), 
    (1591, '2016-08-10', ''), 
    (1591, '2016-08-11', 'AL'), 
    (1591, '2016-08-12', ''), 
    (1082, '2016-02-01', ''), 
    (1082, '2016-02-02', ''), 
    (1082, '2016-02-03', ''), 
    (1082, '2016-02-04', ''), 
    (1082, '2016-02-05', 'MX'), 
    (1082, '2016-02-06', '-'), 
    (1082, '2016-02-07', '-'), 
    (1082, '2016-02-08', '-'), 
    (1082, '2016-02-09', '-'), 
    (1082, '2016-02-10', '-'), 
    (1082, '2016-02-11', '-'), 
    (1082, '2016-02-12', 'MX'); 

    SELECT * FROM @Customers ORDER BY uid, code_date ASC 

Répondre

1
declare @x varchar(1000) = '' 

update @Customers 
set @x = value = (case when @x <> '' and value not in ('-',@x) then '' else @x end) + (case when value = '-' then '' when value = @x then '' else value end) 
where value <> '' 
4
/* Test Data & Table */ 
DECLARE @Customers TABLE 
    (Dates datetime, 
    Customer integer, 
    Value integer) 

    INSERT INTO @Customers 
    VALUES ('20100101', 1, 12), 
     ('20100101', 2, NULL), 
     ('20100101', 3, 32), 
     ('20100101', 4, 42), 
     ('20100101', 5, 15), 
     ('20100102', 1, NULL), 
     ('20100102', 2, NULL), 
     ('20100102', 3, 39), 
     ('20100102', 4, NULL), 
     ('20100102', 5, 16), 
     ('20100103', 1, 13), 
     ('20100103', 2, 24), 
     ('20100103', 3, NULL), 
     ('20100103', 4, NULL), 
     ('20100103', 5, 21), 
     ('20100104', 1, 14), 
     ('20100104', 2, NULL), 
     ('20100104', 3, NULL), 
     ('20100104', 4, 65), 
     ('20100104', 5, 23) ; 

/* CustCTE - This gives us a RowNum to allow us to build the recursive CTE CleanCust */ 
WITH CustCTE 
      AS (SELECT Customer, 
         Value, 
         Dates, 
         ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Dates) RowNum 
       FROM  @Customers), 

/* CleanCust - A recursive CTE. This runs down the list of values for each customer, checking the Value column, if it is null it gets the previous non NULL value.*/ 
     CleanCust 
      AS (SELECT Customer, 
         ISNULL(Value, 0) Value, /* Ensure we start with no NULL values for each customer */ 
         Dates, 
         RowNum 
       FROM  CustCte cur 
       WHERE  RowNum = 1 
       UNION ALL 
       SELECT Curr.Customer, 
         ISNULL(Curr.Value, prev.Value) Value, 
         Curr.Dates, 
         Curr.RowNum 
       FROM  CustCte curr 
       INNER JOIN CleanCust prev ON curr.Customer = prev.Customer 
              AND curr.RowNum = prev.RowNum + 1) 

/* Update the base table using the result set from the recursive CTE */ 
    UPDATE trg 
    SET Value = src.Value 
    FROM @Customers trg 
    INNER JOIN CleanCust src ON trg.Customer = src.Customer 
           AND trg.Dates = src.Dates 

/* Display the results */ 
SELECT * FROM @Customers 
+0

@ user7020195 Cette solution ne résout pas la ma question. J'essaie de remplir les valeurs '-' entre la même valeur 'AL' ou 'MX' avec l'une ou l'autre. – Tee

+0

@ user7020195 Alors désolé! La solution était correcte. Je n'ai pas vérifié correctement au départ. Merci – Tee

0

Pour une requête select, il suffit d'utiliser outer apply:

select t.*, coalesce(t.value, t2.value) as new_value 
from t outer apply 
    (select top 1 t2.* 
     from t t2 
     where t2.uid = t.uid and t2.code_date < t.code_date and t2.value is not null 
     order by t2.code_date desc 
    ) t2; 

Vous pouvez utiliser la même logique dans un update.

En tant update, ce serait:

update t 
    set value = t2.new_value 
    from t outer apply 
     (select top 1 t2.* 
      from t t2 
      where t2.uid = t.uid and t2.code_date < t.code_date and t2.value is not null 
      order by t2.code_date desc 
     ) t2 
    where t.value is null;