sql - SQL:如何用上一行值填充空单元格?

标签 sql tsql sql-server-2008

我需要在不使用循环和相关子查询的情况下,使用SQL生成下表中的“必需”列。在SQL 2008中可能吗?

Date    Customer   Value   Required   Rule
20100101       1      12         12
20100101       2                  0   If no value assign 0
20100101       3      32         32
20100101       4      42         42
20100101       5      15         15
20100102       1                 12   Take last known value
20100102       2                  0   Take last known value
20100102       3      39         39
20100102       4                 42   Take last known value
20100102       5      16         16
20100103       1      13         13
20100103       2      24         24
20100103       3                 39   Take last known value
20100103       4                 42   Take last known value
20100103       5      21         21
20100104       1      14         14
20100104       2                 24   Take last known value
20100104       3                 39   Take last known value
20100104       4      65         65
20100104       5      23         23


基本上,我用那个客户的最后知道的值填充空的“值”单元格。请记住,最后一行可能没有有效值,因此您必须从前一行中选择有效值。

最佳答案

法伊兹

关于以下查询,根据我的理解,它可以满足您的要求。注释解释了每个步骤。看看在线图书上的CTE。甚至可以将该示例更改为对SQL 2008使用新的MERGE命令。

/* Test Data & Table */
DECLARE @Customers TABLE
    (Dates datetime,
     Customer integer,
     Value integer) 

    INSERT  INTO @Customers
    VALUES  ('20100101', 1, 12),
        ('20100101', 2, NULL),
        ('20100101', 3, 32),
        ('20100101', 4, 42),
        ('20100101', 5, 15),
        ('20100102', 1, NULL),
        ('20100102', 2, NULL),
        ('20100102', 3, 39),
        ('20100102', 4, NULL),
        ('20100102', 5, 16),
        ('20100103', 1, 13),
        ('20100103', 2, 24),
        ('20100103', 3, NULL),
        ('20100103', 4, NULL),
        ('20100103', 5, 21),
        ('20100104', 1, 14),
        ('20100104', 2, NULL),
        ('20100104', 3, NULL),
        ('20100104', 4, 65),
        ('20100104', 5, 23) ;

/* CustCTE - This gives us a RowNum to allow us to build the recursive CTE CleanCust */
WITH    CustCTE
          AS (SELECT    Customer,
                        Value,
                        Dates,
                        ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Dates) RowNum
              FROM      @Customers),

/* CleanCust - A recursive CTE. This runs down the list of values for each customer, checking the Value column, if it is null it gets the previous non NULL value.*/
        CleanCust
          AS (SELECT    Customer,
                        ISNULL(Value, 0) Value, /* Ensure we start with no NULL values for each customer */
                        Dates,
                        RowNum
              FROM      CustCte cur
              WHERE     RowNum = 1
              UNION ALL
              SELECT    Curr.Customer,
                        ISNULL(Curr.Value, prev.Value) Value,
                        Curr.Dates,
                        Curr.RowNum
              FROM      CustCte curr
              INNER JOIN CleanCust prev ON curr.Customer = prev.Customer
                                           AND curr.RowNum = prev.RowNum + 1)

/* Update the base table using the result set from the recursive CTE */
    UPDATE trg
    SET Value = src.Value
    FROM    @Customers trg
    INNER JOIN CleanCust src ON trg.Customer = src.Customer
                                AND trg.Dates = src.Dates

/* Display the results */
SELECT * FROM @Customers

关于sql - SQL:如何用上一行值填充空单元格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3465847/

相关文章:

sql - 选择顶行和底行

sql - 如何解决 Redshift 错误 : "Missing data for not-null field"?

sql - 将数字转换为小数精度为 3 的数字的正则表达式

sql - 在 SELECT 查询中使用 TOP 1 的性能影响

sql - 具有动态 WHERE 列的参数化 SQL

sql - 以逗号分隔的列的行列表,在其他列上分组

sql - 从最大查询中选择列名

sql-server-2008 - SQL Server 2008 : SELECT FOR UPDATE

mysql - SQL 查询检查列是否包含某些数据

sql - 使用 t-SQL 检索 XML 元素名称