Hive的窗口函数[附实例]

Hive的窗口函数

准备测试数据

创建一张order表,字段分别为name,orderdate,orderprice

create table ordtable
(
name string,
orderdate date,
orderprice double
)  
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE ;

插入测试数据到表中

insert overwrite table ordtable 
select 'Jack','2021-01-01',10
union all 
select 'ROSE','2021-02-01',15
union all 
select 'ROSE','2021-03-01',20
union all 
select 'Bob','2021-04-01',25
union all 
select 'Bob','2021-03-11',30
union all 
select 'Bob','2021-03-21',20	
union all 
select 'Adam','2021-04-11',15
union all 
select 'Adam','2021-03-11',25
union all 
select 'Adam','2021-04-21',25
union all 
select 'Adam','2021-04-25',5;

测试数据如下

+----------------+---------------------+----------------------+--+
| ordtable.name  | ordtable.orderdate  | ordtable.orderprice  |
+----------------+---------------------+----------------------+--+
| Jack           | 2021-01-01          | 10.0                 |
| ROSE           | 2021-02-01          | 15.0                 |
| ROSE           | 2021-03-01          | 20.0                 |
| Bob            | 2021-04-01          | 25.0                 |
| Bob            | 2021-03-11          | 30.0                 |
| Bob            | 2021-03-21          | 20.0                 |
| Adam           | 2021-04-11          | 15.0                 |
| Adam           | 2021-03-11          | 25.0                 |
| Adam           | 2021-04-21          | 10.0                 |
| Adam           | 2021-04-25          | 5.0                  |
+----------------+---------------------+----------------------+--+

聚合函数+over()

用法描述

聚合函数+over(partition by 分组字段 order by 排序字段 排序方式)

函数描述
COUNT(col) OVER ([query_partition_clause] [order_by_clause])返回分区内col到当前行的数量,如果未指定分区则为全表统计,如果未指定排序则为全组统计
SUM(col) OVER ([query_partition_clause] [order_by_clause])返回分区内col到当前行的和,如果未指定分区则为全表统计,如果未指定排序则为全组统计
MIN(col) OVER ([query_partition_clause] [order_by_clause])返回分区内col到当前行的最小值,如果未指定分区则为全表统计,如果未指定排序则为全组统计
MAX(col) OVER ([query_partition_clause] [order_by_clause])返回分区内col到当前行的最大值,如果未指定分区则为全表统计,如果未指定排序则为全组统计
AVG(col) OVER ([query_partition_clause] [order_by_clause])返回分区内col到当前行的平均值,如果未指定分区则为全表统计,如果未指定排序则为全组统计

如果指定[ROWS BETWEEN … AND …],就指定统计从哪儿行到哪儿行的数据

如果不指定ROWS BETWEEN,默认统计窗口为从起点到当前行

SUM,AVG,MIN,MAX用法和COUNT一样

COUNT(col) OVER ([query_partition_clause] [order_by_clause] [ROWS BETWEEN ... AND ...])

OVER (PARTITION BY col ORDER BY col ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) 表示从当前行前三行到当前行

OVER (PARTITION BY col ORDER BY col ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 表示从开始到当前行

OVER (PARTITION BY col ORDER BY col ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) 表示从当前行到结尾

ROWS BETWEEN... AND ... 也就是window子句,有以下参数:

注意:参数为分组内有效,超过分组就无效了

n PRECEDING:往前n行,n为数字
n FOLLOWING:往后n行,n为数字
CURRENT ROW:当前行
UNBOUNDED PRECEDING: 表示从最前面的起点开始
UNBOUNDED FOLLOWING:表示到最后面的终点

聚合函数+over()与不加over()的区别?

以count(col) over()与count(col)举例

count(col) 要与group by一起使用,且只能查询group by后指定的字段,无法查询表中的其他字段。

count(col)+over()可以任意指定查询字段,且可以控制查询的那儿几行。

聚合函数+over()对于每个组返回多行,而聚合函数对于每个组只返回一行数据。

用法示例

以count()+over()举例

COUNT(col) OVER (PARTITION BY col ORDER BY col ROWS BETWEEN ... AND ...)

返回分区内col到当前行的数量,如果未指定分区(partition by)则为全表统计,如果未指定排序(order by)则为全组统计。

OVER (partition by col order by col )中的 partition by等同于group by

OVER (partition by col order by col )中的order by为分区内排序。

ROWS BETWEEN ... AND ...指定统计从第几行到第几行的数据,不写默认从开始到当前行。

未指定分组和排序

表中有多少行统计出的总行数就为多少行,每个name对应的count(*) over()结果一样。

select name,count(*) over() as ordcount from ordtable;
+-------+-----------------+--+
| name  | ordcount  |
+-------+-----------------+--+
| Adam  | 10              |
| Adam  | 10              |
| Adam  | 10              |
| Adam  | 10              |
| Bob   | 10              |
| Bob   | 10              |
| Bob   | 10              |
| ROSE  | 10              |
| ROSE  | 10              |
| Jack  | 10              |
+-------+-----------------+--+
未指定排序

统计每个人在整个表中出现的总次数。

如Adam在表中总共出现了4次,则数量为4。

select name,count(distinct orderprice) over(partition by name) from ordtable;
与以下结果相同
select name,count(*) over(partition by name) from ordtable;
+-------+-----------------+--+
| name  | count_window_0  |
+-------+-----------------+--+
| Adam  | 4               |
| Adam  | 4               |
| Adam  | 4               |
| Adam  | 4               |
| Bob   | 3               |
| Bob   | 3               |
| Bob   | 3               |
| Jack  | 1               |
| ROSE  | 2               |
| ROSE  | 2               |
+-------+-----------------+--+
未指定分组

只按照价格排序。

select name,orderprice,count(*) over(order by orderprice) from ordtable;
+-------+-------------+-----------------+--+
| name  | orderprice  | count_window_0  |
+-------+-------------+-----------------+--+
| Adam  | 5.0         | 1               |
| Adam  | 10.0        | 3               |
| Jack  | 10.0        | 3               |
| Adam  | 15.0        | 5               |
| ROSE  | 15.0        | 5               |
| Bob   | 20.0        | 7               |
| ROSE  | 20.0        | 7               |
| Adam  | 25.0        | 9               |
| Bob   | 25.0        | 9               |
| Bob   | 30.0        | 10              |
+-------+-------------+-----------------+--+
指定排序和分组

按照姓名分组,按照组内价格升序,统计出到当前行每个人出现的次数。

select name,orderprice,count(*) over(partition by name order by orderprice asc) from ordtable;
+-------+-------------+-----------------+--+
| name  | orderprice  | count_window_0  |
+-------+-------------+-----------------+--+
| Adam  | 5.0         | 1               |
| Adam  | 10.0        | 2               |
| Adam  | 15.0        | 3               |
| Adam  | 25.0        | 4               |
| Bob   | 20.0        | 1               |
| Bob   | 25.0        | 2               |
| Bob   | 30.0        | 3               |
| Jack  | 10.0        | 1               |
| ROSE  | 15.0        | 1               |
| ROSE  | 20.0        | 2               |
+-------+-------------+-----------------+--+
加上window子句

行数只在组内有效

SELECT name,orderdate,
orderprice,  -- 该列做其他列的参考
SUM(orderprice) OVER(PARTITION BY name ORDER BY orderprice) AS s1, -- 默认为从起点到当前行
SUM(orderprice) OVER(PARTITION BY name ORDER BY orderprice ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS s2, --从起点到当前行,结果同s1
SUM(orderprice) OVER(PARTITION BY name ORDER BY orderprice ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS s3,   --当前行到最后  
SUM(orderprice) OVER(PARTITION BY name ORDER BY orderprice ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS s4,   --当前行前1行到当前行
SUM(orderprice) OVER(PARTITION BY name ORDER BY orderprice ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS s5    --当前行前1行到当前行后1行
FROM ordtable;
+-------+-------------+-------------+-------+-------+-------+-------+-------+--+
| name  |  orderdate  | orderprice  |  s1   |  s2   |  s3   |  s4   |  s5   |
+-------+-------------+-------------+-------+-------+-------+-------+-------+--+
| Adam  | 2021-04-25  | 5.0         | 5.0   | 5.0   | 55.0  | 5.0   | 15.0  |
| Adam  | 2021-04-21  | 10.0        | 15.0  | 15.0  | 50.0  | 15.0  | 30.0  |
| Adam  | 2021-04-11  | 15.0        | 30.0  | 30.0  | 40.0  | 25.0  | 50.0  |
| Adam  | 2021-03-11  | 25.0        | 55.0  | 55.0  | 25.0  | 40.0  | 40.0  |
| Bob   | 2021-03-21  | 20.0        | 20.0  | 20.0  | 75.0  | 20.0  | 45.0  |
| Bob   | 2021-04-01  | 25.0        | 45.0  | 45.0  | 55.0  | 45.0  | 75.0  |
| Bob   | 2021-03-11  | 30.0        | 75.0  | 75.0  | 30.0  | 55.0  | 55.0  |
| Jack  | 2021-01-01  | 10.0        | 10.0  | 10.0  | 10.0  | 10.0  | 10.0  |
| ROSE  | 2021-02-01  | 15.0        | 15.0  | 15.0  | 35.0  | 15.0  | 35.0  |
| ROSE  | 2021-03-01  | 20.0        | 35.0  | 35.0  | 20.0  | 35.0  | 35.0  |
+-------+-------------+-------------+-------+-------+-------+-------+-------+--+

窗口函数

用法描述

中文易懂函数描述
LEAD(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式)LEAD (scalar_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause)lead括号里有三个参数,第一个是字段名,第二个是数量N,取分组排序后比该条记录序号大N个的对应记录的对应字段的值,如果字段名为field,N为1,就是取分组排序后下一条记录的field值,会有一个新的字段来作为这个函数的值。第三个参数是如果取值为NUll时的默认值。
LAG(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式)LAG (scalar_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause)lag括号里里有三个参数,第一个是字段名,第二个是数量N,取分组排序后比该条记录序号小N个的对应记录的指定字段的值,如果字段名为field,N为1,就是取分组排序后上一条记录的field值,会有一个新的字段来作为这个函数的值。第三个参数是如果取值为NUll时的默认值。
FIRST_VALUE(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式)FIRST_VALUE(col[,Boolean]) OVER ([query_partition_clause] order_by_clause)这最多需要两个参数。第一个参数是你想要的第一个值的列,第二个(可选)参数必须是一个布尔值,默认为false。如果设置为true,则跳过空值。FIRST_VALUE 取分组内排序后,第一个值。
LAST_VALUE(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式)LAST_VALUE(col[,Boolean) OVER ([query_partition_clause] order_by_clause)这最多需要两个参数。第一个参数是你想要的最后一个值的列,第二个(可选)参数必须是一个布尔值,默认为false。如果设置为true,则跳过空值。LAST_VALUE 取分组内排序后,最后一个值。

LEAD函数和LAG函数

lead函数返回分组内当前行后n行的数据,如果没有为null

返回当前行后1行的数据

select name,orderprice,LEAD(orderprice,1) over() from ordtable;
+-------+-------------+----------------+--+
| name  | orderprice  | lead_window_0  |
+-------+-------------+----------------+--+
| Adam  | 5.0         | 10.0           |
| Adam  | 10.0        | 25.0           |
| Adam  | 25.0        | 15.0           |
| Adam  | 15.0        | 20.0           |
| Bob   | 20.0        | 30.0           |
| Bob   | 30.0        | 25.0           |
| Bob   | 25.0        | 20.0           |
| ROSE  | 20.0        | 15.0           |
| ROSE  | 15.0        | 10.0           |
| Jack  | 10.0        | NULL           |
+-------+-------------+----------------+--+

按照姓名分组排序,返回分组内当前行后1行的数据

select name,orderprice,LEAD(orderprice,1) over(partition by name order by orderprice asc) from ordtable;
+-------+-------------+----------------+--+
| name  | orderprice  | lead_window_0  |
+-------+-------------+----------------+--+
| Adam  | 5.0         | 10.0           |
| Adam  | 10.0        | 15.0           |
| Adam  | 15.0        | 25.0           |
| Adam  | 25.0        | NULL           |
| Bob   | 20.0        | 25.0           |
| Bob   | 25.0        | 30.0           |
| Bob   | 30.0        | NULL           |
| Jack  | 10.0        | NULL           |
| ROSE  | 15.0        | 20.0           |
| ROSE  | 20.0        | NULL           |
+-------+-------------+----------------+--+

lag函数与lead函数相反,lag函数返回分组内当前行前n行的数据,如果没有为null

select name,orderprice,lag(orderprice,1) over() from ordtable;
+-------+-------------+---------------+--+
| name  | orderprice  | lag_window_0  |
+-------+-------------+---------------+--+
| Adam  | 5.0         | NULL          |
| Adam  | 10.0        | 5.0           |
| Adam  | 25.0        | 10.0          |
| Adam  | 15.0        | 25.0          |
| Bob   | 20.0        | 15.0          |
| Bob   | 30.0        | 20.0          |
| Bob   | 25.0        | 30.0          |
| ROSE  | 20.0        | 25.0          |
| ROSE  | 15.0        | 20.0          |
| Jack  | 10.0        | 15.0          |
+-------+-------------+---------------+--+

FIRST_VALUE函数和LAST_VALUE函数

FIRST_VALUE返回分组内排序后,第一个值

select name,orderprice,FIRST_VALUE(orderprice) over() from ordtable;
+-------+-------------+-----------------------+--+
| name  | orderprice  | first_value_window_0  |
+-------+-------------+-----------------------+--+
| Adam  | 5.0         | 5.0                   |
| Adam  | 10.0        | 5.0                   |
| Adam  | 25.0        | 5.0                   |
| Adam  | 15.0        | 5.0                   |
| Bob   | 20.0        | 5.0                   |
| Bob   | 30.0        | 5.0                   |
| Bob   | 25.0        | 5.0                   |
| ROSE  | 20.0        | 5.0                   |
| ROSE  | 15.0        | 5.0                   |
| Jack  | 10.0        | 5.0                   |
+-------+-------------+-----------------------+--+

返回按照名字分组排序后,组内第一个值

select name,orderprice,FIRST_VALUE(orderprice) over(partition by name order by orderprice asc) from ordtable;
+-------+-------------+-----------------------+--+
| name  | orderprice  | first_value_window_0  |
+-------+-------------+-----------------------+--+
| Adam  | 5.0         | 5.0                   |
| Adam  | 10.0        | 5.0                   |
| Adam  | 15.0        | 5.0                   |
| Adam  | 25.0        | 5.0                   |
| Bob   | 20.0        | 20.0                  |
| Bob   | 25.0        | 20.0                  |
| Bob   | 30.0        | 20.0                  |
| Jack  | 10.0        | 10.0                  |
| ROSE  | 15.0        | 15.0                  |
| ROSE  | 20.0        | 15.0                  |
+-------+-------------+-----------------------+--+

LAST_VALUE返回分组内排序后,最后一个值

select name,orderprice,LAST_VALUE(orderprice) over() from ordtable;
+-------+-------------+----------------------+--+
| name  | orderprice  | last_value_window_0  |
+-------+-------------+----------------------+--+
| Adam  | 5.0         | 10.0                 |
| Adam  | 10.0        | 10.0                 |
| Adam  | 25.0        | 10.0                 |
| Adam  | 15.0        | 10.0                 |
| Bob   | 20.0        | 10.0                 |
| Bob   | 30.0        | 10.0                 |
| Bob   | 25.0        | 10.0                 |
| ROSE  | 20.0        | 10.0                 |
| ROSE  | 15.0        | 10.0                 |
| Jack  | 10.0        | 10.0                 |
+-------+-------------+----------------------+--+

分析函数

用法描述

函数描述
RANK() OVER ([query_partition_clause] order_by_clause)生成数据项在分组中的排名,排名相等会在名次中留下空位
ROW_NUMBER() OVER ([query_partition_clause] order_by_clause)从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列
DENSE_RANK() OVER ([query_partition_clause] order_by_clause)生成数据项在分组中的排名,排名相等会在名次中不会留下空位
CUME_DIST() OVER ([query_partition_clause] order_by_clause)小于等于当前值的行数/分组内总行数
PERCENT_RANK() OVER ([query_partition_clause] order_by_clause)分组内当前行的RANK值-1/ 分组内总行数-1
NTILE(num) OVER ([query_partition_clause] order_by_clause)把有序的数据集合 平均分配指定的数量(num)个桶中, 将桶号分配给每一行。如果不能平均分配,则优先分配较小编号的桶,并且各个桶中能放的行数最多相差1,也就是将分组数据按照顺序切分成n片,返回当前切片值。

更改测试数据

因为之前的测试数据不太合理,重新插入一些测试数据

insert overwrite table ordtable 
select 'Bob','2021-03-01',35
union all 
select 'Bob','2021-03-01',15
union all 
select 'Bob','2021-04-01',40
union all 
select 'Bob','2021-03-11',40
union all 
select 'Adam','2021-03-21',25	
union all 
select 'Adam','2021-04-11',15
union all 
select 'Adam','2021-03-11',20
union all 
select 'Adam','2021-04-21',20
union all 
select 'Adam','2021-04-25',5;

ROW_NUMBER函数、RANK函数和DENSE_RANK函数

ROW_NUMBER函数从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列,举例如当有两个人成绩相同时,也会分出个排名第1和第2名。

RANK函数生成数据项在分组中的排名,排名相等会在名次中留下空位,举例如当有两个人成绩相同时,会并列第1名,但没有第2名,比他们两个人成绩低一点的人排名第3名

DENSE_RANK函数生成数据项在分组中的排名,排名相等会在名次中不会留下空位,举例如当有两个人成绩相同时,会并列第1名,但第2名,比他们两个人成绩低一点的人排名第2名

只按照价格排序+排名

select name,orderprice,
ROW_NUMBER() over(order by orderprice desc) as r1,
RANK() over(order by orderprice desc) as r2,
DENSE_RANK() over(order by orderprice desc) as r3
from ordtable;
+-------+-------------+-----+-----+-----+--+
| name  | orderprice  | r1  | r2  | r3  |
+-------+-------------+-----+-----+-----+--+
| Bob   | 40.0        | 1   | 1   | 1   |
| Bob   | 40.0        | 2   | 1   | 1   |
| Bob   | 35.0        | 3   | 3   | 2   |
| Adam  | 25.0        | 4   | 4   | 3   |
| Adam  | 20.0        | 5   | 5   | 4   |
| Adam  | 20.0        | 6   | 5   | 4   |
| Adam  | 15.0        | 7   | 7   | 5   |
| Bob   | 15.0        | 8   | 7   | 5   |
| Adam  | 5.0         | 9   | 9   | 6   |
+-------+-------------+-----+-----+-----+--+

统计按照姓名分组,组内价格排序+排名

select name,orderprice,
ROW_NUMBER() over(partition by name order by orderprice desc) as r1,
RANK() over(partition by name order by orderprice desc) as r2,
DENSE_RANK() over(partition by name order by orderprice desc) as r3
from ordtable;
+-------+-------------+-----+-----+-----+--+
| name  | orderprice  | r1  | r2  | r3  |
+-------+-------------+-----+-----+-----+--+
| Adam  | 25.0        | 1   | 1   | 1   |
| Adam  | 20.0        | 2   | 2   | 2   |
| Adam  | 20.0        | 3   | 2   | 2   |
| Adam  | 15.0        | 4   | 4   | 3   |
| Adam  | 5.0         | 5   | 5   | 4   |
| Bob   | 40.0        | 1   | 1   | 1   |
| Bob   | 40.0        | 2   | 1   | 1   |
| Bob   | 35.0        | 3   | 3   | 2   |
| Bob   | 15.0        | 4   | 4   | 3   |
+-------+-------------+-----+-----+-----+--+

CUME_DIST 函数

CUME_DIST 函数小于等于当前值的行数/分组内总行数

select name,orderprice,CUME_DIST() over(partition by name order by orderprice) from ordtable;
+-------+-------------+---------------------+--+
| name  | orderprice  | cume_dist_window_0  |
+-------+-------------+---------------------+--+
| Adam  | 5.0         | 0.2                 |
| Adam  | 15.0        | 0.4                 |
| Adam  | 20.0        | 0.8                 |
| Adam  | 20.0        | 0.8                 |
| Adam  | 25.0        | 1.0                 |
| Bob   | 15.0        | 0.25                |
| Bob   | 35.0        | 0.5                 |
| Bob   | 40.0        | 1.0                 |
| Bob   | 40.0        | 1.0                 |
+-------+-------------+---------------------+--+

PERCENT_RANK函数

PERCENT_RANK函数分组内当前行的RANK值-1/ 分组内总行数-1

select name,orderprice,PERCENT_RANK() over(partition by name order by orderprice) from ordtable;
+-------+-------------+------------------------+--+
| name  | orderprice  | percent_rank_window_0  |
+-------+-------------+------------------------+--+
| Adam  | 5.0         | 0.0                    |
| Adam  | 15.0        | 0.25                   |
| Adam  | 20.0        | 0.5                    |
| Adam  | 20.0        | 0.5                    |
| Adam  | 25.0        | 1.0                    |
| Bob   | 15.0        | 0.0                    |
| Bob   | 35.0        | 0.3333333333333333     |
| Bob   | 40.0        | 0.6666666666666666     |
| Bob   | 40.0        | 0.6666666666666666     |
+-------+-------------+------------------------+--+

NTILE函数

NTILE函数把有序的数据 平均分配 到 指定数量(num)个桶中, 将桶号分配给每一行。桶号为1到num。如果不能平均分配,则优先分配较小编号的桶,并且各个桶中能放的行数最多相差1,也就是将分组数据按照顺序切分成num片,返回当前切片值。

假如有6行数据,这4行数据为1个分组内,如果此时将数据分为2个桶,前3行数据为1个桶内,桶号为1;后3行数据为1个桶内,桶号为2。

SELECT name,orderprice,
NTILE(1) OVER(partition by name order by orderprice) AS n1,  --将分组内数据分成1片,按照价格排序
NTILE(2) OVER(partition by name order by orderprice) AS n2,  --将分组内数据分成2片,按照价格排序
NTILE(3) OVER(partition by name order by orderprice) AS n3,  --将分组内数据分成3片,按照价格排序
FROM ordtable; 
+-------+-------------+-----+-----+-----+--+
| name  | orderprice  | n1  | n2  | n3  |
+-------+-------------+-----+-----+-----+--+
| Adam  | 5.0         | 1   | 1   | 1   |
| Adam  | 15.0        | 1   | 1   | 1   |
| Adam  | 20.0        | 1   | 1   | 2   |
| Adam  | 20.0        | 1   | 2   | 2   |
| Adam  | 25.0        | 1   | 2   | 3   |
| Bob   | 15.0        | 1   | 1   | 1   |
| Bob   | 35.0        | 1   | 1   | 1   |
| Bob   | 40.0        | 1   | 2   | 2   |
| Bob   | 40.0        | 1   | 2   | 3   |
+-------+-------------+-----+-----+-----+--+

n2=1表示分组内前2分之1的数据,因为按照价格从低到高升序排序,所以为前2分之一最低价格的数据。

n2=2表示分组内前2分之1最高价格的数据。

n3=1表示分组内前3分之1最低价格的数据。

参考网址

hive官网

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值