2013-05-21 1 views
5

Ho i dati sottostanti nella mia tabella.Come ottenere il valore precedente per i valori null

| Id | FeeModeId |Name  | Amount| 
    --------------------------------------------- 
    | 1 | NULL  | NULL  | 20 | 
    | 2 | 1   | Quarter-1 | 5000 | 
    | 3 | NULL  | NULL  | 2000 |  
    | 4 | 2   | Quarter-2 | 8000 | 
    | 5 | NULL  | NULL  | 5000 | 
    | 6 | NULL  | NULL  | 2000 | 
    | 7 | 3   | Quarter-3 | 6000 | 
    | 8 | NULL  | NULL  | 4000 | 

Come scrivere tale query per ottenere al di sotto di uscita ...

| Id | FeeModeId |Name  | Amount| 
    --------------------------------------------- 
    | 1 | NULL  | NULL  | 20 | 
    | 2 | 1   | Quarter-1 | 5000 | 
    | 3 | 1   | Quarter-1 | 2000 |  
    | 4 | 2   | Quarter-2 | 8000 | 
    | 5 | 2   | Quarter-2 | 5000 | 
    | 6 | 2   | Quarter-2 | 2000 | 
    | 7 | 3   | Quarter-3 | 6000 | 
    | 8 | 3   | Quarter-3 | 4000 | 
+0

utilizzare una funzione GAL – Randy

+0

Quale versione di SQL Server? –

+1

Grazie, è utile, ma nel mio caso la differenza di valore precedente non è fissa, qualche tempo 2 record, qualche tempo 3, può essere qualsiasi intervallo. –

risposta

2

Prova:

select 
    a.ID, 
    ISNULL(a.FeeModeId, x.FeeModeId) FeeModeId, 
    ISNULL(a.Name, x.Name) Name, 
    a.Amount 
from tbl a 
outer apply 
(select top 1 FeeModeId, Name 
    from tbl b 
    where b.ID<a.ID and 
     b.Amount is not null and 
     b.FeeModeId is not null and 
     a.FeeModeId is null order by ID desc)x 

O

select 
    ID, 
    ISNULL(FeeModeId, bFeeModeId) FeeModeId, 
    ISNULL(Name, bName) Name, 
    Amount 
From(
    select 
     a.ID , a.FeeModeId, a.Name, a.Amount, 
     b.ID bID, b.FeeModeId bFeeModeId, b.Name bName, 
     MAX(b.FeeModeId) over (partition by a.ID) mx 
    from tbl a left join tbl b on b.ID<a.ID 
    and b.FeeModeId is not null 
)x 
where bFeeModeId=mx or mx is null 
2

provare questo -

SELECT Id, 
     CASE 
     WHEN Feemodeid IS NOT NULL THEN 
      Feemodeid 
     ELSE 
      (SELECT Feemodeid 
      FROM Table_Name t_2 
      WHERE t_2.Id = (SELECT MAX(Id) 
           FROM Table_Name t_3 
          WHERE t_3.Id < t_1.Id 
           AND Feemodeid IS NOT NULL)) 
     END Feemodeid, 
     CASE 
     WHEN NAME IS NOT NULL THEN 
      NAME 
     ELSE 
      (SELECT NAME 
      FROM Table_Name t_2 
      WHERE t_2.Id = (SELECT MAX(Id) 
           FROM Table_Name t_3 
          WHERE t_3.Id < t_1.Id 
           AND NAME IS NOT NULL)) 
     END NAME, 
     Amount 
    FROM Table_Name t_1 
2
SELECT 
    T.ID, 
    ISNULL(T.FeeModeId, 
    (SELECT TOP 1 FeeModeId 
     FROM TableName AS T1 
     WHERE ID < T.ID AND FeeModeId IS NOT NULL 
     ORDER BY ID DESC)) AS FeeModeId, 
    ISNULL(Name, 
    (SELECT TOP 1 Name 
    FROM TableName 
    WHERE ID < T.ID AND Name IS NOT NULL 
    ORDER BY ID DESC)) AS Name, 
    T.Amount 
FROM 
    TableName AS T 
9

Dal momento che siete su SQL Server 2012 ... qui è una versione che usa quello. Potrebbe essere più veloce di altre soluzioni, ma devi testarlo sui tuoi dati.

sum() over() farà una somma parziale ordinata per Id aggiungendo 1 quando ci sono un valore nella colonna e mantenendo il valore corrente null valori. La somma parziale calcolata viene quindi utilizzata per partizionare il risultato in first_value() over(). Il primo valore ordinato da Id per ogni "gruppo" di righe generate dalla somma parziale ha il valore desiderato.

select T.Id, 
     first_value(T.FeeModeId) 
      over(partition by T.NF 
       order by T.Id 
       rows between unbounded preceding and current row) as FeeModeId, 
     first_value(T.Name)  
      over(partition by T.NS 
       order by T.Id 
       rows between unbounded preceding and current row) as Name, 
     T.Amount 
from (
    select Id, 
      FeeModeId, 
      Name, 
      Amount, 
      sum(case when FeeModeId is null then 0 else 1 end) 
       over(order by Id) as NF, 
      sum(case when Name is null then 0 else 1 end) 
       over(order by Id) as NS 
    from YourTable 
    ) as T 

SQL Fiddle

qualcosa che funziona pre SQL Server 2012:

select T1.Id, 
     T3.FeeModeId, 
     T2.Name, 
     T1.Amount 
from YourTable as T1 
    outer apply (select top(1) Name 
       from YourTable as T2 
       where T1.Id >= T2.Id and 
        T2.Name is not null 
       order by T2.Id desc) as T2 
    outer apply (select top(1) FeeModeId 
       from YourTable as T3 
       where T1.Id >= T3.Id and 
        T3.FeeModeId is not null 
       order by T3.Id desc) as T3 

SQL Fiddle

1
id name 
1 toto 
2 NULL 
3 NULL 
4 titi 
5 NULL 
6 NULL 
7 tutu 
8 NULL 
9 NULL 


SELECT 
     id_table 
     ,name 
FROM 
     (
      SELECT 
        T_01.id AS 'id_table' 
        ,max(T_02.id) AS 'id_name' 
      FROM 
        names AS T_01 
        cross join 
        (
          SELECT 
           id 
           ,name 
          FROM 
           names 
          WHERE 
           name IS NOT NULL 
        ) AS T_02 
      WHERE 
        T_02.id <= T_01.id 
      GROUP BY 
        T_01.id 
     ) AS tt02 
     left join names 
     ON names.id = tt02.id_name 


id_table name 
1   toto 
2   toto 
3   toto 
4   titi 
5   titi 
6   titi 
7   tutu 
8   tutu 
9   tutu