SQL填充空值

时间:2015-01-15 11:25:03

标签: sql null

我有一个表,其中有一些行由日期填充,一些行具有日期但其余字段为空。寻找最有效的sql脚本来填补制造和销售价格的缺失值,我不希望更改其他空值(注意价格变化)。我想要跟随包含空值的行的相同品牌和价格。

表格的示例:

Sale_Dates  | Make  | Sale_Price | Year | Color
2015-01-01  |  Ford | 20000.00   |2012  | Blue
2015-01-02  |  NULL | NULL       |NULL  | NULL    
2015-01-03  |  NULL | NULL       |NULL  | NULL
2015-01-04  |  Ford | 30000.00   |NULL  | NULL
2015-01-05  |  NULL | NULL       |NULL  | NULL

预期产出的例子:

Sale_Dates  | Make  | Sale_Price | Year | Color
2015-01-01  |  Ford | 20000.00   |2012  | Blue
2015-01-02  |  Ford | 20000.00   |NULL  | NULL    
2015-01-03  |  Ford | 20000.00   |NULL  | NULL
2015-01-04  |  Ford | 30000.00   |NULL  | NULL
2015-01-05  |  Ford | 30000.00   |NULL  | NULL

2 个答案:

答案 0 :(得分:1)

由于您在评论中提及row_number,我假设您有window functions。 (除了MySQL之外,每个现代的RDBMS都有它们。)然后有一个简单的解决方案:

SELECT sale_date
     , max(make)       OVER (PARTITION BY grp) AS make
     , max(sale_price) OVER (PARTITION BY grp) AS sale_price
     , year, color
FROM  (
   SELECT *, count(make) OVER (ORDER BY sale_date) AS grp
   FROM   tbl
   ORDER  BY sale_date
   ) sub;

假设 makesale_price或NULL或 都是非空的。

Postgres的

SQL Fiddle

更多解释:

答案 1 :(得分:0)

尽管CURSOR有性能缺陷,但此时您可以更好地使用CURSOR,否则您需要检查每条记录的每个NOT NULL值。使用此功能时,您可以将最后NOT NULL值保留在变量中。

注意:我发布此答案,希望您的数据库为SQL SERVER

样本表

CREATE TABLE #TEMP(Sale_Dates  DATE,MAKE VARCHAR(30),Sale_Price NUMERIC(18,2),[YEAR] INT,[COLOR] VARCHAR(20))

INSERT INTO #TEMP
SELECT '2015-01-01'  ,  'Ford' , 20000.00   ,2012  , 'Blue'
UNION ALL
SELECT '2015-01-02'  ,  NULL , NULL       ,NULL  , NULL    
UNION ALL
SELECT '2015-01-03'  ,  NULL , NULL       ,NULL  , NULL
UNION ALL
SELECT '2015-01-04'  ,  'Maruti' , 30000.00   ,NULL  , NULL
UNION ALL
SELECT '2015-01-05'  ,  NULL , NULL       ,NULL  , NULL

<强> QUERY

DECLARE @Sale_Dates DATE
DECLARE @MAKE VARCHAR(30)
DECLARE @Sale_Price NUMERIC(20,2)=0
DECLARE @Previous_MAKE VARCHAR(30)
DECLARE @Previous_Sale_Price NUMERIC(20,2)=0

-- Here you declare which all columns you need to loop in Cursor
DECLARE CUR CURSOR FOR 
SELECT Sale_Dates,MAKE,Sale_Price
FROM #TEMP
ORDER BY Sale_Dates;

OPEN CUR

-- Loop starts from here and selects each Seq and Amount of each record in each loop 
FETCH NEXT FROM CUR INTO @Sale_Dates,@MAKE,@Sale_Price

WHILE @@FETCH_STATUS = 0
BEGIN

    -- Updates with previous NOT NULL value
    IF(@MAKE IS NULL)
    BEGIN
        UPDATE #TEMP SET MAKE = @Previous_MAKE
        WHERE Sale_Dates = @Sale_Dates
    END

    -- Updates with previous NOT NULL value
    IF(@Sale_Price IS NULL)
    BEGIN
        UPDATE #TEMP SET Sale_Price = @Previous_Sale_Price
        WHERE Sale_Dates = @Sale_Dates
    END

    -- Store previous NOT NULL value
    IF(@MAKE IS NOT NULL)
    BEGIN
        SET @Previous_MAKE =  @MAKE
    END

    -- Store previous NOT NULL value
    IF(@Sale_Price IS NOT NULL)
    BEGIN
        SET @Previous_Sale_Price =  @Sale_Price
    END

    -- Fetches next record and increments the loop
    FETCH NEXT FROM CUR INTO @Sale_Dates,@MAKE,@Sale_Price
END 

CLOSE CUR;
DEALLOCATE CUR;