6

为SQL Server 2008 R2最新的非NULL值替换NULL值在结果集系列(SQL Server 2008 R2中)

我有一个结果,看起来像这样(注[价格]是数字,NULL低于代表 NULL值,结果集是由PRODUCT_ID和时间戳)

product timestamp   price 
------- ---------------- ----- 
    5678 2008-01-01 12:00 12.34 
    5678 2008-01-01 12:01 NULL 
    5678 2008-01-01 12:02 NULL 
    5678 2008-01-01 12:03 23.45 
    5678 2008-01-01 12:04 NULL 

我想变换来设置(基本)副本从最新的前行中的非空值,以产生一个结果结果排序看起来像这样:

product timestamp   price 
------- ---------------- ----- 
    5678 2008-01-01 12:00 12.34 
    5678 2008-01-01 12:01 12.34 
    5678 2008-01-01 12:02 12.34 
    5678 2008-01-01 12:03 23.45 
    5678 2008-01-01 12:04 23.45 

我没有找到任何合计/窗口化功能,让我做到这一点(再次这只需要SQL Server 2008 R2的。)

我希望能找到适合做一个分析聚合函数我,像...

LAST_VALUE(price) OVER (PARTITION BY product_id ORDER BY timestamp) 

,但我似乎还没有找到任何方式在窗口做一个“累积最新的非空值”(开往窗口前行,而不是整个分区)

除了创建一个表值用户定义函数,我有没有任何内建可以完成这个任务?


UPDATE:

显然,此功能可在 '德纳' CTP,但不能在SQL Server 2008 R2。

LAST_VALUE http://msdn.microsoft.com/en-us/library/hh231517%28v=SQL.110%29.aspx

我只是希望它是SQL Server 2008中它的问世在甲骨文(因为10gR2中至少)提供,我可以做同样的事情在MySQL 5.1中,使用局部变量。

http://download.oracle.com/docs/cd/E14072_01/server.112/e10592/functions083.htm

+0

你说的是哪功能迪纳利这是可用的,但不是2008 R2? –

回答

8

你可以尝试以下方法:

*更新**

-- Test Data 
DECLARE @YourTable TABLE(Product INT, Timestamp DATETIME, Price NUMERIC(16,4)) 

INSERT INTO @YourTable 
SELECT 5678, '20080101 12:00:00', 12.34 
UNION ALL 
SELECT 5678, '20080101 12:01:00', NULL 
UNION ALL 
SELECT 5678, '20080101 12:02:00', NULL 
UNION ALL 
SELECT 5678, '20080101 12:03:00', 23.45 
UNION ALL 
SELECT 5678, '20080101 12:04:00', NULL 

;WITH CTE AS 
(
    SELECT * 
    FROM @YourTable 
) 

-- Query 
SELECT A.Product, A.Timestamp, ISNULL(A.Price,B.Price) Price 
FROM CTE A 
OUTER APPLY ( SELECT TOP 1 * 
       FROM CTE 
       WHERE Product = A.Product AND Timestamp < A.Timestamp 
       AND Price IS NOT NULL 
       ORDER BY Product, Timestamp DESC) B 

--Results 
Product Timestamp Price 
5678 2008-01-01 12:00:00.000 12.3400 
5678 2008-01-01 12:01:00.000 12.3400 
5678 2008-01-01 12:02:00.000 12.3400 
5678 2008-01-01 12:03:00.000 23.4500 
5678 2008-01-01 12:04:00.000 23.4500 
+0

APPLY关键字对我来说是新的。我会给这个镜头。谢谢! – spencer7593

+0

@ spencer7593 - 让我知道它是怎么回事。 – Lamak

+1

@ spencer7593 - 此外,您可以在此链接上找到有关“APPLY”运算符的一些文档:http://technet.microsoft.com/en-us/library/ms175156.aspx – Lamak

2

试试这个:

;WITH SortedData AS 
(
    SELECT 
     ProductID, TimeStamp, Price, 
     ROW_NUMBER() OVER(PARTITION BY ProductID ORDER BY TimeStamp DESC) AS 'RowNum' 
    FROM dbo.YourTable 
) 
UPDATE SortedData 
SET Price = (SELECT TOP 1 Price 
      FROM SortedData sd2 
     WHERE sd2.RowNum > SortedData.RowNum 
      AND sd2.Price IS NOT NULL) 
WHERE 
    SortedData.Price IS NULL 

基本上,CTE创建排序的列表按时间戳(降序) - 新的第一。只要找到NULL,就会找到包含NOT NULL价格的下一行,并使用该值以NULL价格更新该行。

1

我有一个表格,其中包含以下数据。我想用先前的值更新薪水列中的所有空值而不用空值。

表:

id name salary 
1 A  4000 
2 B 
3 C 
4 C 
5 D  2000 
6 E 
7 E 
8 F  1000 
9 G  2000 
10 G  3000 
11 G  5000 
12 G 

这里是为我的作品查询。

select a.*,first_value(a.salary)over(partition by a.value order by a.id) as abc from 
(
    select *,sum(case when salary is null then 0 else 1 end)over(order by id) as value from test)a 

输出:

id name salary Value abc 
1 A  4000 1  4000 
2 B    1  4000 
3 C    1  4000 
4 C    1  4000 
5 D  2000 2  2000 
6 E    2  2000 
7 E    2  2000 
8 F  1000 3  1000 
9 G  2000 4  2000 
10 G  3000 5  3000 
11 G  5000 6  5000 
12 G    6  5000