Postgresql 窗口函数的使用方法
导入数据库连接
- python版本 3.8
- 数据库软件postgresql 版本12.0
- ipython-sql 版本 4.0
- 目的 在jupyter notebook 界面使用数据库,实现数据中的窗口函数演示
# import sqlalchemy
#
# sqlalchemy.create_engine('postgresql://postgres:1234@localhost/postgres ')
%load_ext sql
## ipython-sql 载入sql命令环境
%sql postgresql://postgres:1234@localhost/postgres
## 连接数据库,用户名postgres密码1234
%%sql
DROP TABLE IF EXISTS "public"."products";
CREATE TABLE "public"."products" (
"id" varchar(10) COLLATE "default",
"name" text COLLATE "default",
"price" numeric,
"uid" varchar(14) COLLATE "default",
"type" varchar(100) COLLATE "default"
)
WITH (OIDS=FALSE);
BEGIN;
INSERT INTO "public"."products" VALUES ('0006', 'iPhone X', '9600', null, '电器');
INSERT INTO "public"."products" VALUES ('0012', '电视', '3299', '4', '电器');
INSERT INTO "public"."products" VALUES ('0004', '辣条', '5.6', '4', '零食');
INSERT INTO "public"."products" VALUES ('0007', '薯条', '7.5', '1', '零食');
INSERT INTO "public"."products" VALUES ('0009', '方便面', '3.5', '1', '零食');
INSERT INTO "public"."products" VALUES ('0005', '铅笔', '7', '4', '文具');
INSERT INTO "public"."products" VALUES ('0014', '作业本', '1', null, '文具');
INSERT INTO "public"."products" VALUES ('0001', '鞋子', '27', '2', '衣物');
INSERT INTO "public"."products" VALUES ('0002', '外套', '110.9', '3', '衣物');
INSERT INTO "public"."products" VALUES ('0013', '围巾', '93', '5', '衣物');
INSERT INTO "public"."products" VALUES ('0008', '香皂', '17.5', '2', '日用品');
INSERT INTO "public"."products" VALUES ('0010', '水杯', '27', '3', '日用品');
INSERT INTO "public"."products" VALUES ('0015', '洗发露', '36', '1', '日用品');
INSERT INTO "public"."products" VALUES ('0011', '毛巾', '15', '1', '日用品');
INSERT INTO "public"."products" VALUES ('0003', '手表', '1237.55', '5', '电器');
INSERT INTO "public"."products" VALUES ('0016', '绘图笔', '15', null, '文具');
INSERT INTO "public"."products" VALUES ('0017', '汽水', '3.5', null, '零食');
COMMIT;
* postgresql://postgres:***@localhost/postgres
Done.
Done.
Done.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
1 rows affected.
Done.
[]
%%sql
select * from public.products
* postgresql://postgres:***@localhost/postgres
17 rows affected.
id | name | price | uid | type |
---|
0006 | iPhone X | 9600 | None | 电器 |
0012 | 电视 | 3299 | 4 | 电器 |
0004 | 辣条 | 5.6 | 4 | 零食 |
0007 | 薯条 | 7.5 | 1 | 零食 |
0009 | 方便面 | 3.5 | 1 | 零食 |
0005 | 铅笔 | 7 | 4 | 文具 |
0014 | 作业本 | 1 | None | 文具 |
0001 | 鞋子 | 27 | 2 | 衣物 |
0002 | 外套 | 110.9 | 3 | 衣物 |
0013 | 围巾 | 93 | 5 | 衣物 |
0008 | 香皂 | 17.5 | 2 | 日用品 |
0010 | 水杯 | 27 | 3 | 日用品 |
0015 | 洗发露 | 36 | 1 | 日用品 |
0011 | 毛巾 | 15 | 1 | 日用品 |
0003 | 手表 | 1237.55 | 5 | 电器 |
0016 | 绘图笔 | 15 | None | 文具 |
0017 | 汽水 | 3.5 | None | 零食 |
%%sql
select type, name,price,row_number() over( order by price asc) as xuhao from public.products
--- 这里的窗口函数可以实现序号列,还可以按照over内的指定的列排序,该语句是按照price列进行升序排列
* postgresql://postgres:***@localhost/postgres
17 rows affected.
type | name | price | xuhao |
---|
文具 | 作业本 | 1 | 1 |
零食 | 汽水 | 3.5 | 2 |
零食 | 方便面 | 3.5 | 3 |
零食 | 辣条 | 5.6 | 4 |
文具 | 铅笔 | 7 | 5 |
零食 | 薯条 | 7.5 | 6 |
日用品 | 毛巾 | 15 | 7 |
文具 | 绘图笔 | 15 | 8 |
日用品 | 香皂 | 17.5 | 9 |
日用品 | 水杯 | 27 | 10 |
衣物 | 鞋子 | 27 | 11 |
日用品 | 洗发露 | 36 | 12 |
衣物 | 围巾 | 93 | 13 |
衣物 | 外套 | 110.9 | 14 |
电器 | 手表 | 1237.55 | 15 |
电器 | 电视 | 3299 | 16 |
电器 | iPhone X | 9600 | 17 |
%%sql
select type, name,price,rank() over( partition by type order by price asc) as rank from public.products
--- 这里实现分类排序,可以按照分类之间内部的价格排序,
--- 可能会出现并列的现象,同时序号会出现间断的情况
* postgresql://postgres:***@localhost/postgres
17 rows affected.
type | name | price | rank |
---|
电器 | 手表 | 1237.55 | 1 |
电器 | 电视 | 3299 | 2 |
电器 | iPhone X | 9600 | 3 |
零食 | 汽水 | 3.5 | 1 |
零食 | 方便面 | 3.5 | 1 |
零食 | 辣条 | 5.6 | 3 |
零食 | 薯条 | 7.5 | 4 |
日用品 | 毛巾 | 15 | 1 |
日用品 | 香皂 | 17.5 | 2 |
日用品 | 水杯 | 27 | 3 |
日用品 | 洗发露 | 36 | 4 |
文具 | 作业本 | 1 | 1 |
文具 | 铅笔 | 7 | 2 |
文具 | 绘图笔 | 15 | 3 |
衣物 | 鞋子 | 27 | 1 |
衣物 | 围巾 | 93 | 2 |
衣物 | 外套 | 110.9 | 3 |
%%sql
select type, name,price,dense_rank() over( partition by type order by price asc) as ds_rank from public.products
--- 这里实现分类排序,可以按照分类之间内部的价格排序,
--- 可能会出现并列的现象,同时序号不少,注意辣条的排名从rank的第三名变成了第二名
* postgresql://postgres:***@localhost/postgres
17 rows affected.
type | name | price | ds_rank |
---|
电器 | 手表 | 1237.55 | 1 |
电器 | 电视 | 3299 | 2 |
电器 | iPhone X | 9600 | 3 |
零食 | 汽水 | 3.5 | 1 |
零食 | 方便面 | 3.5 | 1 |
零食 | 辣条 | 5.6 | 2 |
零食 | 薯条 | 7.5 | 3 |
日用品 | 毛巾 | 15 | 1 |
日用品 | 香皂 | 17.5 | 2 |
日用品 | 水杯 | 27 | 3 |
日用品 | 洗发露 | 36 | 4 |
文具 | 作业本 | 1 | 1 |
文具 | 铅笔 | 7 | 2 |
文具 | 绘图笔 | 15 | 3 |
衣物 | 鞋子 | 27 | 1 |
衣物 | 围巾 | 93 | 2 |
衣物 | 外套 | 110.9 | 3 |
%%sql
select type, name,price,percent_rank() over( partition by type order by price asc) as ps_rank from public.products
--- 这里实现分类排序,可以按照分类之间内部的价格排序,
--- 百分比排名
* postgresql://postgres:***@localhost/postgres
17 rows affected.
type | name | price | ps_rank |
---|
电器 | 手表 | 1237.55 | 0.0 |
电器 | 电视 | 3299 | 0.5 |
电器 | iPhone X | 9600 | 1.0 |
零食 | 汽水 | 3.5 | 0.0 |
零食 | 方便面 | 3.5 | 0.0 |
零食 | 辣条 | 5.6 | 0.666666666666667 |
零食 | 薯条 | 7.5 | 1.0 |
日用品 | 毛巾 | 15 | 0.0 |
日用品 | 香皂 | 17.5 | 0.333333333333333 |
日用品 | 水杯 | 27 | 0.666666666666667 |
日用品 | 洗发露 | 36 | 1.0 |
文具 | 作业本 | 1 | 0.0 |
文具 | 铅笔 | 7 | 0.5 |
文具 | 绘图笔 | 15 | 1.0 |
衣物 | 鞋子 | 27 | 0.0 |
衣物 | 围巾 | 93 | 0.5 |
衣物 | 外套 | 110.9 | 1.0 |
%%sql
select type, name,price,cume_dist() over( partition by type order by price asc) as cd_cume from public.products
--- 这里实现分类排序,可以按照分类之间内部的价格排序,
--- 累计百分比
* postgresql://postgres:***@localhost/postgres
17 rows affected.
type | name | price | cd_cume |
---|
电器 | 手表 | 1237.55 | 0.333333333333333 |
电器 | 电视 | 3299 | 0.666666666666667 |
电器 | iPhone X | 9600 | 1.0 |
零食 | 汽水 | 3.5 | 0.5 |
零食 | 方便面 | 3.5 | 0.5 |
零食 | 辣条 | 5.6 | 0.75 |
零食 | 薯条 | 7.5 | 1.0 |
日用品 | 毛巾 | 15 | 0.25 |
日用品 | 香皂 | 17.5 | 0.5 |
日用品 | 水杯 | 27 | 0.75 |
日用品 | 洗发露 | 36 | 1.0 |
文具 | 作业本 | 1 | 0.333333333333333 |
文具 | 铅笔 | 7 | 0.666666666666667 |
文具 | 绘图笔 | 15 | 1.0 |
衣物 | 鞋子 | 27 | 0.333333333333333 |
衣物 | 围巾 | 93 | 0.666666666666667 |
衣物 | 外套 | 110.9 | 1.0 |
%%sql
select type, name,price,ntile(2) over( partition by type order by price asc) as fenzu from public.products
--- 这里实现分类排序,可以按照分类之间内部的价格排序,
--- 最大化均分,分桶
* postgresql://postgres:***@localhost/postgres
17 rows affected.
type | name | price | fenzu |
---|
电器 | 手表 | 1237.55 | 1 |
电器 | 电视 | 3299 | 1 |
电器 | iPhone X | 9600 | 2 |
零食 | 汽水 | 3.5 | 1 |
零食 | 方便面 | 3.5 | 1 |
零食 | 辣条 | 5.6 | 2 |
零食 | 薯条 | 7.5 | 2 |
日用品 | 毛巾 | 15 | 1 |
日用品 | 香皂 | 17.5 | 1 |
日用品 | 水杯 | 27 | 2 |
日用品 | 洗发露 | 36 | 2 |
文具 | 作业本 | 1 | 1 |
文具 | 铅笔 | 7 | 1 |
文具 | 绘图笔 | 15 | 2 |
衣物 | 鞋子 | 27 | 1 |
衣物 | 围巾 | 93 | 1 |
衣物 | 外套 | 110.9 | 2 |
窗口函数和聚合函数同时使用
%%sql
select id,type,name,price,
sum(price) over(partition by type) 类别金额合计,
sum(price) over(order by type)/ sum(price) over() 类别总金额占所有金额的占比,
round(price /sum(price) over(partition by type),3) 金额占类别金额占比,
rank() over(partition by type order by price desc) 排名,
sum(price) over() 金额总计
from public.products
order by type, price asc
* postgresql://postgres:***@localhost/postgres
17 rows affected.
id | type | name | price | 类别金额合计 | 类别总金额占所有金额的占比 | 金额占类别金额占比 | 排名 | 金额总计 |
---|
0003 | 电器 | 手表 | 1237.55 | 14136.55 | 0.97452786940621326964 | 0.088 | 3 | 14506.05 |
0012 | 电器 | 电视 | 3299 | 14136.55 | 0.97452786940621326964 | 0.233 | 2 | 14506.05 |
0006 | 电器 | iPhone X | 9600 | 14136.55 | 0.97452786940621326964 | 0.679 | 1 | 14506.05 |
0009 | 零食 | 方便面 | 3.5 | 20.1 | 0.97591349816111208772 | 0.174 | 3 | 14506.05 |
0017 | 零食 | 汽水 | 3.5 | 20.1 | 0.97591349816111208772 | 0.174 | 3 | 14506.05 |
0004 | 零食 | 辣条 | 5.6 | 20.1 | 0.97591349816111208772 | 0.279 | 2 | 14506.05 |
0007 | 零食 | 薯条 | 7.5 | 20.1 | 0.97591349816111208772 | 0.373 | 1 | 14506.05 |
0011 | 日用品 | 毛巾 | 15 | 95.5 | 0.98249695816573085023 | 0.157 | 4 | 14506.05 |
0008 | 日用品 | 香皂 | 17.5 | 95.5 | 0.98249695816573085023 | 0.183 | 3 | 14506.05 |
0010 | 日用品 | 水杯 | 27 | 95.5 | 0.98249695816573085023 | 0.283 | 2 | 14506.05 |
0015 | 日用品 | 洗发露 | 36 | 95.5 | 0.98249695816573085023 | 0.377 | 1 | 14506.05 |
0014 | 文具 | 作业本 | 1 | 23 | 0.98408250350715735848 | 0.043 | 3 | 14506.05 |
0005 | 文具 | 铅笔 | 7 | 23 | 0.98408250350715735848 | 0.304 | 2 | 14506.05 |
0016 | 文具 | 绘图笔 | 15 | 23 | 0.98408250350715735848 | 0.652 | 1 | 14506.05 |
0001 | 衣物 | 鞋子 | 27 | 230.9 | 1.00000000000000000000 | 0.117 | 3 | 14506.05 |
0013 | 衣物 | 围巾 | 93 | 230.9 | 1.00000000000000000000 | 0.403 | 2 | 14506.05 |
0002 | 衣物 | 外套 | 110.9 | 230.9 | 1.00000000000000000000 | 0.480 | 1 | 14506.05 |