Как использовать значение из строки выше, когда значение данного столбца равно нулю? - PullRequest
3 голосов
/ 07 июня 2011

У меня есть таблица элементов по дате (каждая строка - новая дата). Я вытягиваю значение из другого столбца D. Мне нужно его заменить, хотя 0. Мне нужна следующая логика: когда D = 0 для этой даты, используйте значение в столбце D с предыдущей даты.

На самом деле, по правде говоря, мне нужно сказать, что когда D равно 0, используйте значение с самой поздней даты, когда D не было 0, но первое получит меня большую часть пути туда.

Есть ли способ построить эту логику? Может быть, CTE?

Большое спасибо.

PS Я использую SSMS 2008.

РЕДАКТИРОВАТЬ: Сначала я не очень ясно. Значение, которое я хочу изменить, не является датой. Я хочу изменить значение в D с последним ненулевым значением из D, основываясь на дате.

Ответы [ 5 ]

4 голосов
/ 07 июня 2011

Может быть, следующий запрос может помочь вам.Он использует OUTER APPLY для получения результатов.Снимок экрана # 1 показывает данные примера и результаты запроса к данным образца.Этот запрос можно написать лучше, но это то, что я мог бы придумать прямо сейчас.

Надеюсь, это поможет.

SELECT      ITM.Id
        ,   COALESCE(DAT.New_D, ITM.D) AS D
        ,   ITM.DateValue
FROM        dbo.Items   ITM
OUTER APPLY (
                SELECT      
                TOP 1       D   AS New_D
                FROM        dbo.Items DAT
                WHERE       DAT.DateValue   < ITM.DateValue
                AND         DAT.D           <> 0
                AND         ITM.D           = 0
                ORDER BY    DAT.DateValue DESC
            ) DAT

Снимок экрана № 1:

1

1 голос
/ 07 июня 2011
UPDATE t
Set value = SELECT value
              FROM table 
             WHERE date = (SELECT MAX(t1.date)
                             FROM table t1
                            WHERE t1.value != 0
                              AND t1.date < t.date)
 FROM table t
WHERE t.value = 0
0 голосов
/ 07 июня 2011
SELECT t.id,
    CASE WHEN t.D = 0 THEN t0.D
         ELSE t.D END
FROM table AS t
LEFT JOIN table AS t0
    ON t0.time = 
    (
        SELECT MAX(time) FROM t0
        WHERE t0.time < t.time
        AND t0.D != 0
    )

или, если вы хотите полностью избежать агрегатов,

SELECT t.id,
   CASE WHEN t.D = 0 THEN t0.D
       ELSE t.D END
FROM table AS t
LEFT JOIN table AS t0
    ON t0.time < t.time
LEFT JOIN table AS tx
    ON tx.time > t0.time
WHERE t0.D != 0
    AND tx.D != 0
    AND tx.id IS NULL  -- i.e. there isn't any
0 голосов
/ 07 июня 2011

Как насчет:

SELECT
    i.ID,
    i.DateValue,
    D = CASE WHEN I.D <> 0 THEN I.D ELSE X.D END
FROM
    Items I
    OUTER APPLY (
        SELECT TOP 1 S.D 
        FROM Items S 
        WHERE S.DATEVALUE < I.DATEVALUE AND S.D <> 0 
        ORDER BY S.DATEVALUE DESC
    ) X
0 голосов
/ 07 июня 2011

Может быть, что-то подобное в сценарии обновления ...

SET myTable.D = (
   SELECT TOP 1 myTable2.D 
   FROM myTable2
   WHERE myTable2.myDateField < myTable.myDateField
   AND myTable2.D != 0
   ORDER BY myTable2.myDateField DESC)

Предполагается, что вы действительно хотите обновить данные, а не просто заменить значения для выбора.запрос.

...