2013-05-21 2 views
5

У меня есть данные ниже в таблице.Как получить предыдущее значение для нулевых значений

| 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 | 

Как написать такой запрос, чтобы получить ниже выходной ...

| 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

использование ЛАГ функция – Randy

+0

Какую версию SQL Server? –

+1

Thanx, его полезно, но в моем случае предыдущая разница значений не исправить, некоторое время 2 записи, некоторое время 3, это может быть любой диапазон. –

ответ

2

Пожалуйста, попробуйте:

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 

ИЛИ

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

попробовать это -

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

Поскольку вы на SQL Server 2012 ... здесь это версия, которая использует это. Это может быть быстрее, чем другие решения, но вы должны проверить это на своих данных.

sum() over() будет делать бегущую сумму по заказу Id добавления 1, когда есть значение в столбце и сохранения текущего значения для null значений. Затем вычисляемая текущая сумма используется для разделения результата на first_value() over(). Первое значение, упорядоченное по Id для каждой «группы» строк, генерируемых текущей суммой, имеет нужное значение.

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

Что-то, что будет работать заранее 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 
Смежные вопросы