password: hqd
plaintext自动换行:关放大阅读展开代码1. 业务数据库中涉及表 省份表(全量),sku表(全量),订单表(增量),订单明细表(增量) 2. ods层数据加载 load data命令加载入hive的ods表中 3. dwd层 订单明细表 业务过程:下单 粒度:一次下单中的一个商品 维度:sku,地区,渠道等等 事实:该商品的下单金额 4. dws层 sku粒度,省份的下单汇总表 5. ads 使用省份粒度分组,where分区过滤,sum下单金额 6. 数据调度 ads ——》datax--》mysql 7. superset可视化展示
plaintext自动换行:关放大阅读展开代码1. 涉及的表 日志数据中的页面浏览日志 2. ods层数据加载 日志数据的话,是全部存在在ods层的一张日志表,有五种日志数据 3. dwd层页面浏览事实表 页面浏览事实表 业务过程:页面浏览 粒度:一次浏览中的一个页面 维度:所属的会话,地区,渠道,所用的设备,当前使用的软件版本等等 事实:该次浏览的时长等 4. dws层(1d表) 会话,页面(渠道)粒度的浏览汇总表 最近1日访问时长,最近1日的访问的页面数 5. ads层 访客数:count(distinct mid) 会话数:count(1) 会话平均停留时长:avg(duration_time_1d) 会话平均浏览页面数:avg(page_id_1d) 跳出率:该渠道统计下,一个会话中只浏览了一个页面的会话数 / 该渠道的会话总数 count(if(page_id_1d = 1,1,0)) / count(1) ECHO is off.
plaintext自动换行:关放大阅读展开代码用户流失统计 1. 涉及的表 日志数据 2. ods层数据加载 日志数据的话,是全部存在在ods层的一张日志表,有五种日志数据, 3. dwd层登录事实表 用户登录事实表 业务过程:登录页面 粒度:一个用户的一次登录 维度:所属的会话,地区,渠道,所用的设备,当前使用的软件版本等等 事实:一次登录 4. dws层(td表) 用户粒度至今的登录情况汇总表,每个分区存放的是历史至今的用户登录 情况的统计 比如历史至今的登录次数,历史至今最后一次登录时间 5. ads层 流失用户:比如5号最近3日的流失用户数 回流用户:比如5号最近3日的回流用户数 流失: select 分号, count(1)流失用户数 from 历史至今登录汇总表 where 分区号=5号 and 最后一次登录时间 = 3天前当天 回流: --3日流失用户有哪些? with t1 as( select 分区号, 用户id from 历史至今登录汇总表 where 分区号=5号 and 最后一次登录时间 = 3天前当天或者3天前), --5号登录的用户有那些? t2 as( select 分区号, 用户id from 用户登录事实增量表 where 分区号 = 5号) select count(1)流失用户数 from t1 join t2 on t1.用户id = t2.用户id
plaintext自动换行:关放大阅读展开代码5号最近三日新增留存统计 1. 涉及的表 业务数据库中用户信息表 2. ods层数据加载 用户信息增量表,日志信息 3. dwd层用户注册事实表 用户注册事实表 业务过程:用户注册 粒度:用户注册 维度:注册时的时间,地区,渠道,所用的设备,当前使用的软件版本等等 事实:无 ECHO is off. 用户登录事实表 --》用户登录至今td表 4. dws层(用户登录至今td表) 用户粒度至今的登录情况汇总表,每个分区存放的是历史至今的用户登录 情况的统计 比如历史至今的登录次数,历史至今最后一次登录时间 5. ads层 --5号登录的用户有那些? with t1 as( select 分区号, user_id from 用户登录至今汇总表 where 分区号 = 5号), --最近3日的注册用户数 t2 as( select 分号, userid from 用户注册增量事实表 where 分区号 in(2号,3号,4号)), select t2.分区号, count(1) 注册用户数, count(t1.userid)留存用户数, count(t1.userid)/ count(1)留存率 from t1 right join t2 on t1.user_id = t2.user_id group by t2.分区号
sql自动换行:关放大阅读展开代码ECHO is off. -- 求某个页面同时浏览人数最多的前三个时间段,求出同时浏览人数,和时间段 /* rank nums, start_date, end_date 1 7, 2021-09-27 08:00:00, 2021-09-27 08:30:00 2 6, 2021-09-27 08:30:00, 2021-09-27 09:30:00 2 6, 2021-09-26 13:00:00, 2021-09-27 08:00:00 3 5, 2021-09-27 09:30:00, 2021-09-27 10:30:00 3 5, 2021-10-06 09:10:00, 2021-10-06 10:00:00 */ with t1 as -- 每个用户的跳入时间和跳出时间 (select user_id, in_date, date_add(in_date,duration_time) out_date from dwd_user_page_view upv ),-- union 跳入和跳出 t2 as ( select user_id, in_date, 1 flag from t1 union select user_id, out_date, -1 from t1 ),-- 按照时间升序,累计求和浏览人数 t3 as ( select in_date, sum(flag) over(order by in_date) load_sum from t2 ), t4 as ( -- 按照跳入时间,lead取下一条记录,并对人数降序 select in_date, load_sum, lead(in_date,1,'9999-12-31') upper_bound, dense_rank() over(order by load_sum desc) dr from t3 ) select in_date, upper_bound, load_sum from t4 -- 取前三名 where dr <= 3;
用户的流失和回流统计,以及用户留存分析
sql自动换行:关放大阅读展开代码-- ADS DROP TABLE IF EXISTS ads_order_to_pay_interval_avg; CREATE EXTERNAL TABLE ads_order_to_pay_interval_avg ( `dt` STRING COMMENT '统计日期', `order_to_pay_interval_avg` BIGINT COMMENT '下单到支付时间间隔平均值,单位为秒' ) COMMENT '各品牌商品收藏次数Top3' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/warehouse/gmall/ads/ads_order_to_pay_interval_avg/'; --dwd_trade_trade_flow_acc分区: 普通日期分区[当日完成的流程数据]、9999-99-99分区[未完成的流程数据] insert overwrite table ads_order_to_pay_interval_avg select * from ads_order_to_pay_interval_avg where dt!='2020-06-14' union all select '2020-06-14' dt, avg(unix_timestamp(payment_time) - unix_timestamp(order_time) ) --当日完成支付的订单流程可能完成了,也可能没有完成 from dwd_trade_trade_flow_acc where (dt='9999-99-99' or dt='2020-06-14') and payment_date_id = '2020-06-14'; -- ######################################################################## -- DWD -- 存放订单完成的订单和未完成的订单 订单完成定义: ①下单,支付,确认收货 或者 下单,取消订单 订单未完成: 除了①都是未完成的情况 DROP TABLE IF EXISTS dwd_trade_trade_flow_acc; CREATE EXTERNAL TABLE dwd_trade_trade_flow_acc ( `order_id` STRING COMMENT '订单id', `user_id` STRING COMMENT '用户id', `province_id` STRING COMMENT '省份id', `order_date_id` STRING COMMENT '下单日期id', `order_time` STRING COMMENT '下单时间', `payment_date_id` STRING COMMENT '支付日期id', `payment_time` STRING COMMENT '支付时间', `finish_date_id` STRING COMMENT '确认收货日期id', `finish_time` STRING COMMENT '确认收货时间', `order_original_amount` DECIMAL(16, 2) COMMENT '下单原始价格', `order_activity_amount` DECIMAL(16, 2) COMMENT '下单活动优惠分摊', `order_coupon_amount` DECIMAL(16, 2) COMMENT '下单优惠券优惠分摊', `order_total_amount` DECIMAL(16, 2) COMMENT '下单最终价格分摊', `payment_amount` DECIMAL(16, 2) COMMENT '支付金额' ) COMMENT '交易域交易流程累积快照事实表' PARTITIONED BY (`dt` STRING) STORED AS ORC LOCATION '/warehouse/gmall/dwd/dwd_trade_trade_flow_acc/' TBLPROPERTIES ('orc.compress' = 'snappy'); /* 首日数据加载方式: ods对应表中首日分区存放的是所有历史数据,其中存在未完成和已完成的流程,分别写入流程完成日期分区和9999-99-99分区中 每日数据加载方式: insert overwrite table dwd_trade_trade_flow_acc partition (dt) 当日新增的订单 union all 历史未完成的订单 left join order_info left join order_status */ -- ######################################################################## -- ODS -- 1.支付表 -- 2. 订单表 -- 3. 订单状态表
sql自动换行:关放大阅读展开代码DROP TABLE IF EXISTS ads_order_by_province; CREATE EXTERNAL TABLE ads_order_by_province ( `dt` STRING COMMENT '统计日期', `recent_days` BIGINT COMMENT '最近天数,1:最近1天,7:最近7天,30:最近30天', `province_id` STRING COMMENT '省份ID', `province_name` STRING COMMENT '省份名称', `area_code` STRING COMMENT '地区编码', `iso_code` STRING COMMENT '国际标准地区编码', `iso_code_3166_2` STRING COMMENT '国际标准地区编码', `order_count` BIGINT COMMENT '订单数', `order_total_amount` DECIMAL(16, 2) COMMENT '订单金额' ) COMMENT '各地区订单统计' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/warehouse/gmall/ads/ads_order_by_province/'; DROP TABLE IF EXISTS dws_trade_province_order_nd; CREATE EXTERNAL TABLE dws_trade_province_order_nd ( `province_id` STRING COMMENT '省份id', `province_name` STRING COMMENT '省份名称', `area_code` STRING COMMENT '地区编码', `iso_code` STRING COMMENT '旧版ISO-3166-2编码', `iso_3166_2` STRING COMMENT '新版版ISO-3166-2编码', `order_count_7d` BIGINT COMMENT '最近7日下单次数', `order_original_amount_7d` DECIMAL(16, 2) COMMENT '最近7日下单原始金额', `activity_reduce_amount_7d` DECIMAL(16, 2) COMMENT '最近7日下单活动优惠金额', `coupon_reduce_amount_7d` DECIMAL(16, 2) COMMENT '最近7日下单优惠券优惠金额', `order_total_amount_7d` DECIMAL(16, 2) COMMENT '最近7日下单最终金额', `order_count_30d` BIGINT COMMENT '最近30日下单次数', `order_original_amount_30d` DECIMAL(16, 2) COMMENT '最近30日下单原始金额', `activity_reduce_amount_30d` DECIMAL(16, 2) COMMENT '最近30日下单活动优惠金额', `coupon_reduce_amount_30d` DECIMAL(16, 2) COMMENT '最近30日下单优惠券优惠金额', `order_total_amount_30d` DECIMAL(16, 2) COMMENT '最近30日下单最终金额' ) COMMENT '交易域省份粒度订单最近n日汇总事实表' PARTITIONED BY (`dt` STRING) STORED AS ORC LOCATION '/warehouse/gmall/dws/dws_trade_province_order_nd' TBLPROPERTIES ('orc.compress' = 'snappy'); DROP TABLE IF EXISTS dws_trade_province_order_1d; CREATE EXTERNAL TABLE dws_trade_province_order_1d ( `province_id` STRING COMMENT '省份id', `province_name` STRING COMMENT '省份名称', `area_code` STRING COMMENT '地区编码', `iso_code` STRING COMMENT '旧版ISO-3166-2编码', `iso_3166_2` STRING COMMENT '新版版ISO-3166-2编码', `order_count_1d` BIGINT COMMENT '最近1日下单次数', `order_original_amount_1d` DECIMAL(16, 2) COMMENT '最近1日下单原始金额', `activity_reduce_amount_1d` DECIMAL(16, 2) COMMENT '最近1日下单活动优惠金额', `coupon_reduce_amount_1d` DECIMAL(16, 2) COMMENT '最近1日下单优惠券优惠金额', `order_total_amount_1d` DECIMAL(16, 2) COMMENT '最近1日下单最终金额' ) COMMENT '交易域省份粒度订单最近1日汇总事实表' PARTITIONED BY (`dt` STRING) STORED AS ORC LOCATION '/warehouse/gmall/dws/dws_trade_province_order_1d' TBLPROPERTIES ('orc.compress' = 'snappy'); DROP TABLE IF EXISTS dwd_trade_order_detail_inc; CREATE EXTERNAL TABLE dwd_trade_order_detail_inc ( `id` STRING COMMENT '编号', `order_id` STRING COMMENT '订单id', `user_id` STRING COMMENT '用户id', `sku_id` STRING COMMENT '商品id', `province_id` STRING COMMENT '省份id', `activity_id` STRING COMMENT '参与活动规则id', `activity_rule_id` STRING COMMENT '参与活动规则id', `coupon_id` STRING COMMENT '使用优惠券id', `date_id` STRING COMMENT '下单日期id', `create_time` STRING COMMENT '下单时间', `source_id` STRING COMMENT '来源编号', `source_type_code` STRING COMMENT '来源类型编码', `source_type_name` STRING COMMENT '来源类型名称', `sku_num` BIGINT COMMENT '商品数量', `split_original_amount` DECIMAL(16, 2) COMMENT '原始价格', `split_activity_amount` DECIMAL(16, 2) COMMENT '活动优惠分摊', `split_coupon_amount` DECIMAL(16, 2) COMMENT '优惠券优惠分摊', `split_total_amount` DECIMAL(16, 2) COMMENT '最终价格分摊' ) COMMENT '交易域下单明细事务事实表' PARTITIONED BY (`dt` STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS ORC LOCATION '/warehouse/gmall/dwd/dwd_trade_order_detail_inc/' TBLPROPERTIES ('orc.compress' = 'snappy');
sql自动换行:关放大阅读展开代码DROP TABLE IF EXISTS ads_traffic_stats_by_channel; CREATE EXTERNAL TABLE ads_traffic_stats_by_channel ( `dt` STRING COMMENT '统计日期', `recent_days` BIGINT COMMENT '最近天数,1:最近1天,7:最近7天,30:最近30天', `channel` STRING COMMENT '渠道', `uv_count` BIGINT COMMENT '访客人数', `avg_duration_sec` BIGINT COMMENT '会话平均停留时长,单位为秒', `avg_page_count` BIGINT COMMENT '会话平均浏览页面数', `sv_count` BIGINT COMMENT '会话数', `bounce_rate` DECIMAL(16, 2) COMMENT '跳出率' ) COMMENT '各渠道流量统计' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/warehouse/gmall/ads/ads_traffic_stats_by_channel/'; DROP TABLE IF EXISTS dws_traffic_session_page_view_1d; CREATE EXTERNAL TABLE dws_traffic_session_page_view_1d ( `session_id` STRING COMMENT '会话id', `mid_id` string comment '设备id', `brand` string comment '手机品牌', `model` string comment '手机型号', `operate_system` string comment '操作系统', `version_code` string comment 'app版本号', `channel` string comment '渠道', `during_time_1d` BIGINT COMMENT '最近1日访问时长', `page_count_1d` BIGINT COMMENT '最近1日访问页面数' ) COMMENT '流量域会话粒度页面浏览最近1日汇总表' PARTITIONED BY (`dt` STRING) STORED AS ORC LOCATION '/warehouse/gmall/dws/dws_traffic_session_page_view_1'; DROP TABLE IF EXISTS dwd_traffic_page_view_inc; CREATE EXTERNAL TABLE dwd_traffic_page_view_inc ( `province_id` STRING COMMENT '省份id', --ods_base_province_full `brand` STRING COMMENT '手机品牌', `channel` STRING COMMENT '渠道', `is_new` STRING COMMENT '是否首次启动', `model` STRING COMMENT '手机型号', `mid_id` STRING COMMENT '设备id', `operate_system` STRING COMMENT '操作系统', `user_id` STRING COMMENT '会员id', `version_code` STRING COMMENT 'app版本号', `page_item` STRING COMMENT '目标id ', `page_item_type` STRING COMMENT '目标类型', `last_page_id` STRING COMMENT '上页类型', `page_id` STRING COMMENT '页面ID ', `source_type` STRING COMMENT '来源类型', `date_id` STRING COMMENT '日期id', `view_time` STRING COMMENT '跳入时间', `session_id` STRING COMMENT '所属会话id', ---? `during_time` BIGINT COMMENT '持续时间毫秒' ) COMMENT '页面日志表' PARTITIONED BY (`dt` STRING) STORED AS ORC LOCATION '/warehouse/gmall/dwd/dwd_traffic_page_view_inc' TBLPROPERTIES ('orc.compress' = 'snappy'); /* 页面浏览事实表,主要为每一条浏览记录加上一个会话id: 1. 每条页面日志都会记录当前页面id,和上一次的页面id;取last_page_id 为null的作为一个新会话的开始 if(page.last_page_id is null, concat(common.mid, '_', ts), null) session_point 2. 按照设备id分组,页面访问时间升序排列,使用last_value为每条页面访问日志加上会话id last_value(session_point,true) over (partition by mid order by ts asc) session_id */
sql自动换行:关放大阅读展开代码/* 通过路径分析,可以得到网站页面整体的顺序跳转情况统计,并根据统计结果,对整个页面的设计和调整提供数据支撑 */ DROP TABLE IF EXISTS ads_page_path; CREATE EXTERNAL TABLE ads_page_path ( `dt` STRING COMMENT '统计日期', `source` STRING COMMENT '跳转起始页面ID', `target` STRING COMMENT '跳转终到页面ID', `path_count` BIGINT COMMENT '跳转次数' ) COMMENT '页面浏览路径分析' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/warehouse/gmall/ads/ads_page_path/'; insert overwrite table ads_page_path select * from ads_page_path where dt!='2020-06-14' union all select '2020-06-14' , concat(source,'_',rn), --后续需要将数据导入mysql,以source与target作为联合主键,主键不允许为Null,所以需要处理target为null的情况 nvl(concat(target,'_',rn+1),'None'), count(1) from ( select page_id source, lead(page_id) over (partition by session_id order by view_time asc) target, row_number() over (partition by session_id order by view_time asc) rn from dwd_traffic_page_view_inc where dt = '2020-06-14' ) t1 group by concat(source,'_',rn),concat(target,'_',rn+1);
sql自动换行:关放大阅读展开代码-- 求注册用户1,7,30日内人均支付总金额 -- 同上面的1,7,30日的各个省份GMV统计,只需要额外join用户注册事实表即可
sql自动换行:关放大阅读展开代码DROP TABLE IF EXISTS ads_sku_cart_num_top3_by_cate; CREATE EXTERNAL TABLE ads_sku_cart_num_top3_by_cate ( `dt` STRING COMMENT '统计日期', `category1_id` STRING COMMENT '一级分类ID', `category1_name` STRING COMMENT '一级分类名称', `category2_id` STRING COMMENT '二级分类ID', `category2_name` STRING COMMENT '二级分类名称', `category3_id` STRING COMMENT '三级分类ID', `category3_name` STRING COMMENT '三级分类名称', `sku_id` STRING COMMENT '商品id', `sku_name` STRING COMMENT '商品名称', `cart_num` BIGINT COMMENT '购物车中商品数量', `rk` BIGINT COMMENT '排名' ) COMMENT '各分类商品购物车存量Top3' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/warehouse/gmall/ads/ads_sku_cart_num_top3_by_cate/'; DROP TABLE IF EXISTS dwd_trade_cart_full; CREATE EXTERNAL TABLE dwd_trade_cart_full ( `id` STRING COMMENT '编号', `user_id` STRING COMMENT '用户id', `sku_id` STRING COMMENT '商品id', `sku_name` STRING COMMENT '商品名称', `sku_num` BIGINT COMMENT '加购物车件数' ) COMMENT '交易域购物车周期快照事实表' PARTITIONED BY (`dt` STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS ORC LOCATION '/warehouse/gmall/dwd/dwd_trade_cart_full/' TBLPROPERTIES ('orc.compress' = 'snappy');
分时流量统计(每小时的uv,pv,新访客数)
plaintext自动换行:关放大阅读展开代码(一) # 处理每条浏览数据 .group by(m -> m.getString("mid")) .map(new RichMap(){ Long pv = 1L; Long uv = 0L; Long nv = 0L; 1. 使用valueState存储每个用户当日的首次浏览日期 firstDate 2. 后续每来一条数据就比较firstDate,不同uv置为1 3. 每条浏览日志中都有标记该用户是否为新用户的标志位,可以通过 标志位来判断 }) # 按照软件版本和访问渠道分组,新老客户标识 .keyBy(m -> m.getVc() + m.getCh() + m.getIsNew()) # 5秒的滚动聚合窗口 .window(TumblingEventTimeWindows.of(Time.seconds(5))) # 对窗口中的内容聚合 .reduce(滚动聚合逻辑,输出5s滚动聚合的结果) # 写出到clickhouse .addSink(new ClickhouseSink(...)) (二) sprinboot接口每小时访问clickhouse,并使用sql查询你ch,并 返回数据给sugar 查询sql为: select toHour(stt) hor, sum(uv), sum(pv), sum(if(is_new = '1',1,0)) from dws层页面浏览汇总表 where toYYYYMMDD(stt) = "2023-02-27" group by hor;
搜索关键词统计(每2小时给出系统搜索关键词的前十热词分析)
plaintext自动换行:关放大阅读展开代码(一) 1. 从dwd层页面日志topic中过滤出用户的搜索行为和搜索关键词 2. 由于用户一次可能搜索多个关键词,需要打散关键词(自定义flink sql的制表函数) 3. 开窗聚合 select kw keyword, window_start,window_end, count(1) times from table(TUMBLE(TABLE search, DESCRIPTOR(et), interval '5' second ))group by kw,window_start,window_end 4. 转化为RetractStream并写入到clickhouse 5. 从clickhouse查询
新老客户的流量统计(跳出率,平均的在线时长,平均的访问页面数)
plaintext自动换行:关放大阅读展开代码(一) .keyBy(m -> m.getMid()) .map(new RichMap(){ # 会话统计 Long svCt = 0L; # 页面统计访问 Long pv = 1L; # 上一次访问的页面id为null,即为新会话的开始 if (lastPageId == null) { svCt = 1L; } # 从日志数据中获取页面的访问时长 Long durSum = page.getLong("during_time"); }) .keyBy(e -> e.getVc() + e.getCh() + e.getAr() + e.getIsNew()) .window(TumblingEventTimeWindows.of(Time.seconds(5))) .reduce() .addSink() (二) mapper层向clickhouse查询的sql: select is_new, sum(uv_ct) uv_ct, sum(pv_ct) pv_ct, sum(sv_ct) sv_ct, sum(uj_ct) uj_ct, sum(dur_sum) dur_sum from dws汇总表 where toYYYYMMDD(stt) = '2023-02-27' group by is_new controller层: 平均在线时长: 访问页面总时长 / uv 平均访问页面数: 总访问页面数 / uv
各个活动的补贴率(重大节日各个活动的实时补贴率)
plaintext自动换行:关放大阅读展开代码补贴率:用券的订单明细优惠券减免金额总和/原始金额总和 省略
各个优惠券的补贴率
各个品牌,各个spu的交易统计
最难的
路径分析加用户漏斗:
本文作者:hedeoer
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!