如何用每组的前一列填充 NULL 列?

How to populate NULL column with the previous column per group?

如何用每组的前一行填充 NULL 值?

像这样说,

+--------+---------+--------+
| Date   | Product | Amount |
+        +         +        +
| 7/1/15 | Prod1   | 5      |
| 7/1/15 | Prod2   | 7      |
| 7/1/15 | Prod3   | 9      |
| 8/1/15 | Prod1   | NULL   |
| 8/1/15 | Prod2   | 8      |
| 8/1/15 | Prod3   | NULL   |
| 9/1/15 | Prod1   | 1      |
| 9/1/15 | Prod2   | NULL   |
| 9/1/15 | Prod3   | NULL   |
| 10/1/15| Prod1   | NULL   |
+--------+---------+--------+

实现这样的目标:

+--------+---------+--------+
| Date   | Product | Amount |
+        +         +        +
| 7/1/15 | Prod1   | 5      |
| 7/1/15 | Prod2   | 7      |
| 7/1/15 | Prod3   | 9      |
| 8/1/15 | Prod1   | 5      |
| 8/1/15 | Prod2   | 8      |
| 8/1/15 | Prod3   | 9      |
| 9/1/15 | Prod1   | 1      |
| 9/1/15 | Prod2   | 8      |
| 9/1/15 | Prod3   | 9      |
| 10/1/15| Prod1   | 1      |
+--------+---------+--------+

这有意义吗?我不知道从哪里开始。任何帮助将非常感激。谢谢!

编辑

规则:

举个例子,上面是一个示例数据。

这一行

Date   | Product | Amount
8/1/15 | Prod1   | NULL

它的数量应该用 5 填充,因为它应该在相同的 Product 类别中获得之前的值。

您需要这样的查询:

;WITH t AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Product ORDER BY [Date]) rn
    FROM yourTable)
, tt AS (
    SELECT t1.[Date], t1.Product, t1.Amount, MAX(CASE WHEN t2.Amount IS NOT NULL THEN t2.rn END) AS LastSeq
    FROM t t1
    LEFT JOIN
    t t2 ON t1.Product = t2.Product AND t2.rn <= t1.rn
    GROUP BY t1.[Date], t1.Product, t1.Amount)
SELECT tt.[Date], tt.Product, ISNULL(tt.Amount, t.Amount) As Amount
FROM tt 
JOIN t ON tt.Product = t.Product AND tt.LastSeq = t.rn  
ORDER BY tt.[Date], tt.Product

我要建议cross apply:

update table t cross apply
       (select top 1 t2.*
        from table t2
        where t2.product = t.product and
              t2.date < t.date and
              t2.amount is not null
        order by t2.date desc
       ) toupdate
    set amount = toupdate.amount
    where t.amount is null;

编辑:

如果您知道 NULL 的字符串永远不会太多,您可以这样做:

update table t
     set product = coalesce(lag(amount) over (partition by product order by date),
                            lag(amount, 2) over (partition by product order by date),
                            lag(amount, 3) over (partition by product order by date)
                           )
     where product is null;

或者,或者,只是 运行:

update table t
     set product = lag(amount) over (partition by product order by date)
     where product is null;

直到没有行发生变化。

您可以使用 ISNULL(或 COALESCE)和相关子查询:

SELECT  t.Date, t.Product, 
        Amount = ISNULL(t.Amount, 
                  (SELECT TOP 1 Amount 
                   FROM dbo.TableName t2
                   WHERE t2.Product = t.Product
                   AND t2.Amount IS NOT NULL
                   AND t2.Date <= t.Date
                   ORDER BY t2.Date DESC))
FROM dbo.TableName t

Demo 使用您的示例数据。

我更喜欢 ISNULL 而不是 CAOLESCE 因为后者 will be translated to a CASE that is executed twice. You can read more about the issue at MS-Connect.