Установить основанное решение для обновления нулей на Последнее известное значение в упорядоченной таблице - PullRequest
1 голос
/ 07 февраля 2011

Чтобы сохранить мою чистоту и честь в качестве придурка базы данных, я хочу обновить набор datetime и float, у которого есть несколько нулей в столбце float, так что каждое нулевое значение будет заменено предыдущим (datetime) ненулевым значение.

Моя среда mssql 2k8R2.

Надеюсь, следующий фрагмент достаточно подробно объясняет мои условия победы.

Приветствия и спасибо.

create table #datesAndValues(
    [Date] datetime,
    Val float);
create table #resultsShouldLookLikeThis(
    [Date] datetime,
    Val float);

insert into #datesAndValues 
values  
    ('1/8/11',1.1),
    ('1/7/11',null),
    ('1/6/11',1.2),
    ('1/5/11',null),
    ('1/4/11',null),
    ('1/3/11',1.3),
    ('1/2/11',null),
    ('1/1/11',null);

/*  
    set based code (no loops!!!) goes here to set nulls
    in the above table to the last known good (not null) value,
    thereby making it look like the following table.
*/

insert into #resultsShouldLookLikeThis
values  
    ('1/8/11',1.1),
    ('1/7/11',1.2),
    ('1/6/11',1.2),
    ('1/5/11',1.3),
    ('1/4/11',1.3),
    ('1/3/11',1.3),
    ('1/2/11',null),
    ('1/1/11',null);

--this will tell us if it worked
select 'In old but not new' as [WhichTable], o.*
from    (select * from #datesAndValues
        except select * from #resultsShouldLookLikeThis) o
union all
select 'In new but not old' as [WhichTable], n.*
from    (select * from #resultsShouldLookLikeThis
        except select * from #datesAndValues) n;

drop table #datesAndValues;
drop table #resultsShouldLookLikeThis;

Ответы [ 2 ]

0 голосов
/ 07 февраля 2011
update #datesAndValues set
  Val = (select top 1 Val
         from #datesAndValues as T2
         where
          T2.[Date] < T.[Date] and
          T2.Val is not null
         order by [Date] desc)
from #datesAndValues as T         
where T.Val is null
0 голосов
/ 07 февраля 2011

Здесь есть несколько вещей, на которые следует обратить внимание.

Второй уровень Inline SQL необходим, иначе вы получите неоднозначное #datesAndValues при обновлении.(возможно, есть лучший способ решить эту проблему)

Второе, на что следует обратить внимание, это то, что два значения по-прежнему будут нулевыми, поскольку для 1/1/11 и 1/2/11

* 1009 нет предыдущего значения.* Наконец, как отмечает Мартин.Решение с курсором, вероятно, лучше в любом случае
UPDATE
    #datesAndValues 
SET 
   Val = newVal.val
FROM
    #datesAndValues d1
    INNER JOIN 
    (SELECT 
       maxVal.OldDate,
       newValue.Val 
     FROM 
       #datesAndValues newValue
        INNER JOIN 
        (
                SELECT
                  t.[Date] oldDate, max(t2.[Date]) NewDate
                 FROM 
                   #datesAndValues   t
                   INNER JOIN #datesAndValues  t2
                   ON t.[Date] > t2.Date
                      and t2.Val is not null
                 WHERE
                   t.Val is null

                 GROUP BY
                   t.[Date]
        )  maxVal
        on NewValue.[Date] = maxVal.NewDate)  newVal
        ON d1.Date= newVal.oldDate

Вот альтернатива с использованием DENSE_RANK

WITH Cte as 
(Select 
   dv.Date ,
   dv2.val newval,
    DENSE_RANK () OVER (partition by dv.Date order by dv2.Val) RANK
From 
    #datesAndValues dv
    INNER JOIN #datesAndValues dv2
    ON dv.[date] > dv2.[date]
        AND dv.val is null
       and dv2.val is not null
)
UPDATE 
    #datesAndValues
SET 
    val = Cte.newval
FROM 
    #datesAndValues dv
    INNER JOIN Cte 
    ON dv.Date = cte.Date
WHERE
    Cte.RANK = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...