sql server前值填充

1、问题:如何用前一个非null值填充null?

sql

2、oracle实现前值填充

由于oracle中的函数功能强大,可以通过first_value函数直接实现,因为它有IGNORE参数,而sql server不支持。这里不再展开。

FIRST_VALUE
  { (expr) [ {RESPECT | IGNORE} NULLS ]
  | (expr [ {RESPECT | IGNORE} NULLS ])
  }
  OVER (analytic_clause)

3、sql server实现前值填充

(1) 数据准备

create table fill_null(
id int primary key identity(1,1) not null,
score int default null)

insert into fill_null values(null);
insert into fill_null values(300);
insert into fill_null values(null);
insert into fill_null values(null);
insert into fill_null values(500);
insert into fill_null values(null);
insert into fill_null values(null);

(2) 用前一个非null值填充null

SELECT *
FROM
(
    SELECT f1.id,
           f2.score,
           ROW_NUMBER() OVER(PARTITION BY f1.id ORDER BY f2.id DESC) AS rownumber
    FROM fill_null f1
         LEFT JOIN fill_null f2 ON f1.id >= f2.id
                                   AND f2.score IS NOT NULL
) t
WHERE t.rownumber = 1;

结果:
sql server前值填充

4、sql server中的first_value、last_value函数怎么用?

(1) 语法:

FIRST_VALUE ( scalar_expression ) OVER ([PARTITION BY
partition_expression, … ] ORDER BY sort_expression [ASC | DESC],
… [rows_range_clause])

  • scalar_expression是针对结果集的有序分区的第一行的值计算的表达式。
  • scalar_expression可以是计算为单个值的列,子查询或表达式。它不能是一个Window函数。
  • PARTITION BY子句将结果集的行分配到应用FIRST_VALUE()函数的分区中。 如果不使用PARTITION BY子句,FIRST_VALUE()函数会将整个结果集视为单个分区。
  • ORDER BY子句指定应用FIRST_VALUE()函数的每个分区中行的逻辑顺序。
  • rows_range_clause通过定义起点和终点进一步限制分区内的行。

(2) 案例:
建立一个高三学生的模拟考试分数表,date字段为模考时间,score为模考分数。下面需要得出一下字段:
fst字段,以该生第一次模考成绩填充。
part_fst字段,以该生不同年份的最后一次模考成绩填充。
bounded_lst字段,以该生第一次成绩到当前成绩为窗口,获取该窗口最后一个记录。
lst字段,以该生最后一次模考成绩填充。

WITH test
as
(
    select 1 as id, '20211001' as date,510 as score
    UNION ALL
    select 2, '20211201',520
    UNION ALL
    select 3, '20220501',550
    UNION ALL
    select 4, '20220901',535
    UNION ALL
    select 5, '20230201',570
    UNION ALL
    select 6, '20230501',600
)
SELECT id,
       date,
       score,
       FIRST_VALUE(score) OVER(ORDER BY date) AS fst,
	   FIRST_VALUE(score) OVER(partition by  datepart(yy,date) ORDER BY date) AS part_fst,
       LAST_VALUE(score) OVER(ORDER BY date) AS bounded_lst,
	   LAST_VALUE(score) over(ORDER BY date  ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lst
FROM test;

sql server
(3) 注意:LAST_VALUE和FIRST_VALUE是有区别的;LAST_VALUE是当前窗口的最后一个值,在查询中未指定,默认窗口是从当前分区的第一行到当前行的行。您可以将FIRST_VALUE与deseeding order一起使用,也可以指定一个窗口。
上例中的First_Value(),用法是根据Partition By对数据进行分区,如果忽略Partition By ,那么默认整块数据一个区域,然后根据Order By 进行排序,取出第一个值。
(4) 知识扩展:
分析函数中包含三个分析子句:分组(Partition By), 排序(Order By), 窗口(Window)
窗口就是分析函数分析时要处理的数据范围,就拿SUM来说, 它是SUM窗口中的记录而不是整个分组中的记录(见下面【sum窗口案例】),因此我们在想得到某个栏位的累计值时, 我们需要把窗口指定到该分组中的第一行数据到当前行, 如果你指定该窗口从该分组中的第一行到最后一行,那么该组中的每一个SUM值都会一样,即整个组的总和。窗口子句在这里我只说rows方式的窗口,range方式的这里不提, 此外滑动窗口也不提.。窗口子句中我们经常用到指定第一行,当前行,最后一行这样的三个属性. 第一行是 unbounded preceding, 当前行是 current row, 最后一行是 unbounded following.
出现窗口子句,必须指定Order By子句, 如:

LAST_VALUE(score) over(ORDER BY date  ROWS 
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lst

以上示例指定窗口为整个分组。

当省略窗口子句时:
a) 如果存在Order By则默认的窗口是unbounded preceding and current row
b) 如果同时省略Order By则默认的窗口是unbounded preceding and unbounded following

如果省略分组,则把全部记录当成一个组:
a) 如果存在Order By则默认窗口是unbounded preceding and current row
b) 如果这时省略Order By则窗口默认为unbounded preceding and unbounded following

【sum窗口案例】:

CREATE TABLE B
(modified DATE NOT NULL,
 account  VARCHAR(10) NOT NULL,
 amount   INT
);

insert into B values ('20200715', 'SH1', 1000);
insert into B values ('20200717', 'SH1', 2000);
insert into B values ('20200718', 'SH1', 2500);
insert into B values ('20200722', 'SH1', 3000);

select B.modified, B.AMOUNT, sum(amount) OVER(ORDER BY B.MODIFIED) AS AMOUNT_SUM from B;

运行结果:
sql server sum

参考:http://www.itpub.net/thread-703576-3-1.html
https://blog.csdn.net/wanghai__/article/details/5690102?utm_source=blogxgwz3

5、附录

SQL Server增删改查

10分钟学会SQL server

猜你喜欢

转载自blog.csdn.net/craftsman2020/article/details/107586574
今日推荐