当给定列值为零时,如何使用上面一行中的值?

时间:2011-06-07 14:40:47

标签: sql sql-server sql-server-2008 common-table-expression case-when

我有一个按日期列出的项目表(每一行都是一个新的日期)。我从另一列D中抽出一个值。我需要它来替换0。我需要以下逻辑:当该日期的D = 0时,使用前一日期的D列中的值。

实际上,说实话,我需要它说,当D为0时,使用D不是0的最新日期的值,但是第一个会让我大部分都在那里。

有没有办法构建这个逻辑?也许是CTE?

非常感谢。

PS我正在使用SSMS 2008。

编辑:起初我不太清楚。我想要更改的值不是日期。我希望根据日期更改D中的最新非零值。

5 个答案:

答案 0 :(得分:4)

可能以下查询可能会对您有所帮助。它使用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 :(得分:1)

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

答案 2 :(得分:0)

你可以将这样的东西作为更新脚本的一部分......

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

假设你想要实际更新数据,而不是仅仅为了选择查询而替换值。

答案 3 :(得分:0)

怎么样:

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

答案 4 :(得分: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 = 
    (
        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