1 项目介绍
1.1 项目背景
某互联网电商公司拥有超过50万+门店用户和8000+店铺用户,店铺主要以卖家身份进行销售,门店以买家身份进行购买,每天会产生许多销售订单。根据订单信息以及其他的门店信息,店铺信息,商品信息等进行分析制作不同需求报表,以供业务人员和管理人员每天查看分析,制定相应的措施和提供一些决策依据。从而促进公司的经营和发展,实现公司利益最大化。
本次的项目案例将以某电商销售数据来进行数据分析,例如:我们需要统计各省份门店和店铺的注册数、各省份批发订单指标数据、各阶段门店用户数等。
本项目案例我们将使用以下技术来进行开发:
MySQL -> 数据查询、数据存储
Python -> 执行sql查询语句
Shell -> 执行python文件
Crontab -> 定时调度shell脚本
FineReport -> 数据报表可视化
1.2 项目架构
架构方案介绍:
公司中的各种信息数据都是存储在生产数据库中,此项目案例以mysql数据库为例,将各种数据存储在mysql数据库中
基于数据库的SQL查询语句,结合项目具体需求,实现数据指标查询操作。使用datagrip来快速将数据需求进行SQL指令交互
将项目需求的sql查询代码上传到公司服务器执行,通过python编程语言执行sql语句,实现项目需求各个指标数据的计算,将计算出的指标数据保存到BI mysql数据库中
项目需求指标数据是定时更新的,以便相关人员实时查看分析,使用linux系统服务器中的crontab服务,结合shell编程语言,实现定时执行python脚本文件,更新需求指标数据
通过FineReport BI可视化工具,实现将项目需求指标数据进行报表可视化展示,以供相关人员方便快速查看
1.3 项目数据表
门店表 uc_chain
字段名称 字段解释 字段说明
chain_id 门店id
member_id 买家id/会员id 等同于订单表中buyer_id字段
chain_user App账号登录名
chain_name 门店名称
areaid_1 省份id 地区表中关联字段
areaid_2 市id 地区表中关联字段
areaid_3 县id 地区表中关联字段
chain_status 门店状态:1.正常 2.关闭
is_auth 是否认证:0未认证 1已认证
audit_status 审核状态:0:默认待更新资料 1:待审核(中) 2:已审核 3:已拒绝
add_time 门店添加时间 门店注册时间
update_time 门店修改时间
…
店铺表 uc_store
字段名称 字段解释 字段说明
store_id 店铺id 订单表中store_id
store_name 店铺名称
member_id 买家id 等同于订单表中buyer_id字段
member_name 会员名称
areaid_1 省份id 地区表中关联字段
areaid_2 市id 地区表中关联字段
areaid_3 县id 地区表中关联字段
store_state 店铺状态,0关闭,1开启,2审核中
is_auth 是否认证:0未认证 1已认证 2认证审核中
add_time 店铺添加时间 店铺注册时间
update_time 店铺修改时间
…
地区表 shopnc_area
字段名称 字段解释
area_id 地区id 省市县id
area_name 地区名称(省、市、县)
…
批发订单表 shopnc_pf_orders
字段名 字段解释 字段说明
order_id 订单id
store_id 卖家店铺id 同uc_store表中store_id
buyer_id 买家id 同uc_chain/uc_store表中member_id
add_time 订单生成时间 时间戳
payment_time 订单支付时间 统计订单数据以此时间为准
finnshed_time 订单完成时间
order_amount 订单金额
order_state 订单状态 0(已取消)10(默认):未付款;20:已付款;30:已发货;40:已收货;50:已拒付;60:已关闭(转单成功后关闭) 统计订单以20,30,40为准
order_type 订单类型 3批发订单 5大宗交易
…
CRM系统中客户表 crm_customer
字段名 字段解释 字段说明
customer_id 客户自增id 没有实际意义
out_customer_id 电商门店/店铺id 门店和店铺存在客户表中
is_register 0未注册,1已注册 门店或店铺是否注册
customer_type 客户类型 0未知 1 门店 2 店铺 区分客户为门店还是店铺字段
close_status 关闭状态:门店:1正常 2关闭 / 店铺:0关闭,1开启,2审核中
add_time 添加时间 门店或店铺注册时间
…
ERP系统公司表 shopnc_erp
字段名 字段解释 字段说明
erp_id 归属erp公司id erp系统中的公司id
erp_name erp公司名称 erp系统中的公司名称
area_id_1 区域省份id 和area地区表关联的省份id
…
ERP系统订单表 shopnc_erp_order
字段名 字段解释 字段说明
erp_order_id erp订单主键 订单id
erp_store_id 电商店铺id 店铺表中的店铺id
erp_store_name 电商店铺名称 店铺表中的店铺名称
erp_buyer_id 电商门店chain_id 门店表中的门店id
erp_buyer_name 电商门店chain_name 门店表中的门店名称
erp_order_amount 订单总金额
add_time erp订单生成时间
payment_time erp订单支付时间
erp_id 归属erp id erp系统公司表中的公司id
order_state 电商标准的订单状态 与shopnc_pf_orders表中order_state字段 相同
erp_refund_state 退单状态 0:未退单 1:退单
area_1 省份id
…
品牌代理店门店签约表 daily_operate_agent_brand_name
字段名 字段解释 字段说明
investment_id 招商活动id 除49、54、55、58、69活动外,其他都是品牌代理店活动
investment_name 招商活动名称 品牌代理店名称
chain_id 门店id 签约活动的门店id
state 招商活动状态 待审核,已通过,拒绝 统计数据为招商活动活动状态已通过的门店
date_join_time 活动通过时间 签约门店数以此时间为准
…
品牌代理店门店动销表 agnet_passenger_performance_brand_agency_pfdetail
字段名 字段解释 字段说明
investment_id 招商活动id 除49、54、55、58、69活动外,其他都是品牌代理店活动
chain_id 门店id 动销门店的门店id
type 类型:1,3,5:品牌代理店订单;2,4,6:卫星门店订单 统计数据以1、3、5为准
payment_time 订单支付时间 动销门店数以此时间为准
…
1.4 项目主题需求介绍
统计各省份门店和店铺注册数量
统计各省份批发订单业务进展情况
统计各阶段门店用户数量
统计erp系统中各公司销售订单数据
统计各品牌代理店签约门店数和动销门店数
1.5 主题需求分析流程
需求分析
需求指标计算
编写python脚本
编写shell脚本
定时调度脚本
制作需求报表
报表部署
2 FineReport报表工具学习
2.1 产品简介
2.1.1 FineReport产品简介
FineReport介绍
FineReport报表软件是一款纯Java编写的、集数据展示(报表)和数据录入(表单)功能于一身的企业级web报表工具,它专业、简捷、灵活的特点和无码理念,仅需简单的拖拽操作便可以设计复杂的中国式报表,搭建数据决策分析系统。
特点
功能全面且专业。支持关系型数据库、BI多维数据库的连接取数,支持中国式复杂报表的处理,支持离线填报、多级上报、数据填报,有着安全、完善的权限控制方案等。
设计报表简单高效,学习成本低。类Excel的界面使用户不需任何额外学习成本,零编码开发报表,轻松的拖拽数据,一两分钟内就能完成报表制作。
行业积累丰富。对各个行业都有着自己独到的见解,提供诸如一系列或从上之下、从内到外涉及战略、运营、组织、财务、营销等多个主题的解决方案和实施方案。
2.1.2 FineReport和FineBI的区别
具体差别:
数据引擎方面
FineReport:能跨系统直连数据库,通过SQL创建数据集取数制作报表;
FineBI:直接对接数据库的实时数据与抽取数据的spider计算引擎,用户可以根据数据量、实时性要求、使用频次等,自由选择实时或抽取的方式。
Spider引擎是一个内置的支持数据分片特性的存储引擎,支持分区和XA事务(分布式事务处理是指一个事务可能涉及多个数据库操作),该引擎可以在服务器上建立和远程数据库表之间的链接,操作起来就像操作本地的表一样。并且对后台数据库的引擎没有任何限制。
报表方面
FineReport:CS设计器设计开发报表模板,用户可任意制作所需要的展示效果。比如满足一定条件单元格展示、前端JS交互、超级链接、图形展示等。支持灵活定制各种中国式复杂报表;
CS:全称Client/Server,是客户端和服务器结构;它是软件系统体系结构,通过它可充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。
FineBI:主要提供自助式的OLAP多维数据分析模式;纯BS端自定义拖拽分析报表,业务人员可根据报表需求自行拖拽生成各类分析报表。效果取决于设计者的分析能力。
BS:全称Browser/Server,是浏览器和服务器结构,一般指B/S结构,是WEB兴起后的一种网络结构模式,这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。
使用方面
FineReport:可以用来出固定格式的周报、月报、适合作为正式汇报材料;
FineBI:主要面向业务人员可以自己设计报表进行分析,向自主分析得出结果,辅助企业业务决策。
使用对象和目的
FineReport属于报表工具,报表是企业信息化必不可少统计分析工具,主要实现一些企业固定的月报,季报,关键数据的统计分析,旨在统计或者告诉决策者:过去发生了什么,什么正在发生。 报表系统更着重于短期的运作支持。
FineBI属于商业智能工具,侧重于数据分析,改变之前传统做表的方式,交互性更好,性能更加强大,旨在将企业中现有的数据转化为知识,帮助企业做出明智的业务经营决策。BI关注长期的战略决策,甚至更着重于商业趋势和业务单元的联系而非具体的数据和精确度本身,BI并不是用来代替着眼于日常运做的报表系统的。
2.2 FineReport安装
设计器安装流程如下图所示:
设计器下载
① 打开 FineReport 官网,页面上方选择「产品>产品下载」,进入 FineReport 安装包下载页面。如下图所示:
② 安装包下载页面提供了四种版本的安装包,根据系统选择下载对应版本的安装包,这边以 Windows 64 位系统为例,将 Windows 64 位版本的安装包下载到本地。如下图所示:
设计器安装
-
双击 FineReport 安装文件,会加载安装向导,安装向导加载完毕,会弹出 FineReport 安装程序向导对话框。如下图所示:
-
点击「下一步」,弹出许可协议对话框,勾选「我接受协议」。如下图所示:
-
点击「下一步」,弹出选择安装目录对话框,点击「浏览」,选择 FineReport 安装目录。如下图所示:
注:不建议将 FineReport 设计器安装在系统盘。
-
点击「下一步」,弹出设置最大内存对话框,最大 JVM 内存默认为 2048M,也就是 2G,建议最大 JVM 内存设置为 2G 以上。需要注意的是最大 JVM 内存不能超过本机最大内存。如下图所示:
-
点击「下一步」,弹出选择开始菜单文件夹对话框,根据需求勾选。如下图所示:
-
点击「下一步」,弹出选择附加工作对话框,勾选前两个即可。如下图所示:
-
点击「下一步」,弹出选择文件关联对话框。勾选这两个选项后,以后所有 FRM 和 CPT 后缀的文件默认使用 FineReport 设计器打开。如下图所示:
注:frm 后缀文件是 FineReport 设计的决策报表,cpt 后缀文件是 FineReport 设计的普通报表或聚合报表。
- 点击「下一步」,弹出完成 FineReport 安装程序对话框。如果勾选「运行产品演示」并点击「完成」,FineReport 设计器会自动启动并弹出决策系统设置页面。不勾选「运行产品演示」,设计器不会自动启动。如下图所示:
设计器激活
第一次安装 FineReport 设计器,则启动设计器后,会弹出产品激活对话框。如下图所示:
点击「获取激活码」按钮,会跳转到 激活码获取页面,登录帆软通行证,跳转到首次激活使用的页面,点击「立即获取」,填写完信息后,点击「激活」按钮,激活码会自动呈现在网页上,点击「复制」,在激活对话框的单元格里粘贴激活码,最后点击「使用设计器」按钮激活设计器。
设计器卸载
设计器安装目录%FR_HOME%\下以管理员身份运行uninstall.exe。
弹出卸载窗口,点击「下一步」。如下图所示:
调整设计器分辨率
用户需要调整设计器兼容性,来实现调整设计器界面字体的大小。
在桌面上右击“设计器图标”,选择「属性>兼容性>更改所有用户的设置>更改高 DPI 设置」,勾选「替代高DPI缩放行为」,下拉框选择「系统」 。如下图所示:
==注意:==部分用户若选择「系统」无效时,建议选择「系统增强」。
然后点击「确定」,重启设计器即可。
2.3 FineReport快速入门
2.3.1 普通报表
2.3.1.1 报表设计流程
2.3.1.2 报表效果
在制作这张简单普通报表之前,我们先来看一下报表最终呈现出来的效果,然后我们再根据这个效果来设计报表的样式。
这张报表包含的功能模块:
控件面板:下拉框可以选择地区,点击查询按钮后,只查询出该地区对应的表格和柱形图数据。
表格:表格统计该地区下各销售员每个产品的总销量。
柱形图:柱形图将该地区下各销售员每个产品的总销量以图表的形式进行展示。
介绍完报表的实现效果,下面我们根据报表制作流程图来设计这张简单普通报表。
2.3.1.3 报表制作
2.3.1.3.1 新建数据连接
新建数据连接的目的是让 FineReport 设计器连接数据库,这样报表就可以在数据库中读取、写入或修改数据。
数据连接的方式有两种,分别是连接内置数据库和连接外置数据库。制作这张报表连接的是 FineReport 内置的 SQLite 类型的数据库,有关外置数据库的连接后边内容会介绍。
打开设计器,菜单栏选择「服务器>定义数据连接」。
弹出「定义数据连接」对话框,设计器已经默认连接了一个名为 FRDemo 的内置数据库,点击「测试链接」,弹出「连接成功」提示框,表示数据库 FRDemo 成功与设计器建立连接。接下来就可以从这个数据库中取数用于报表的设计。
2.3.1.3.2 新建报表类型
菜单栏选择「文件>新建普通报表」或者点击「新建普通报表」按钮,新建一张空白的普通报表,如下图所示:
用户可根据需要展示的数据进行页面设置,此处点击菜单栏选择「模板>页面设置」,方向选择纵向,纸张大小选择预定义 A4。或者自定义纸张大小
2.3.1.3.3 新建数据集
数据集通过 SQL 查询语句从已经建立连接的数据库中取数,将数据以二维表的形式保存并显示在数据集管理面板处。简单而言数据集是报表设计时的直接数据来源。
我们制作的这张普通报表将新建两个模板数据集 ds1 和 ds2。
数据集管理面板选择「模板数据集」,点击上方的,在弹出的模板数据集类型选择框中点击「数据库查询」。如下图所示:
在弹出的数据库查询对话框中,写入数据查询语句,新建数据集 ds1,查询并取出「销量」表中的所有数据。如下图所示:
SELECT * FROM 销量;
同理,新建数据集 ds2,写入数据库查询语句,查询并取出每个销售员的销售总量信息。如下图所示:
SELECT 销售员, SUM(销量) AS 销售总量 FROM 销量 GROUP BY 销售员;
新建好数据集之后,可在数据集管理面板查看取出的数据。如下图所示:
至此报表的数据准备工作已经完成,下面对报表的样式进行设计。
2.3.1.3.4 报表设计
2.3.1.3.4.1 表格设计
样式设计
标题:合并 A1~D2 单元格,写入报表标题「地区销售概况」,设置标题为 15号字体,字体加粗并居中。如下图所示:
单元格斜线:在一个单元格中用斜线分隔显示三个标题字段信息,合并A3、B3 单元格,右击合并后的单元格,点击「单元格元素>插入斜线」。系统会弹出一个斜线编辑的对话框,在文本编辑框写入标题字段信息:产品|销售员|地区,此处使用的符号均为英文模式下的符号,同时可以通过添加空格来调整文字的位置。如下图所示:
边框:选中从A1~D5单元格,点击工具栏中的 按钮,在系统弹出的边框设置对话框中,同时添加内部和外部边框。最终样式效果如下图所示:
数据绑定
将数据集中的数据列拖入到对应单元格中。选中地区字段后按住鼠标左键不放,拖动到单元格中,其他字段同理设置。如下图所示:
C5 单元格用于计算每个产品各自的总销量,所以要对 C4 单元格求和,选中 C5 单元格,点击上方快捷按钮中的插入公式,在弹出的公式编辑框中输入公式 SUM(C4)。如下图所示:
D5 单元格用于统计所有产品的总销量,所以要对 D4 单元格求和,同理,在 D5 单元格插入公式 SUM(D4)。
数据绑定最终效果,如下图所示:
属性设置
选中 C3 单元格,让产品字段的数据在表格中横向扩展,默认为纵向扩展,右边属性面板选择「单元格属性>扩展>基本>扩展方向>横向」。如下图所示:
选中C4单元格,由于 A4、B4、C3 单元格的扩展已经确定了唯一的销量值,故 C4 单元格无需扩展,扩展方向为不扩展。
C5和D5单元格也都要设置扩展方向为不扩展。如下图所示:
选中 A1~D5 单元格,点击上方的居中按钮,将表格中的字体「居中」显示。
多数据集关联
当报表中存在不同数据集的数据时,需要通过添加数据过滤条件,建立起不同数据集之间的联系。
我们制作的这张报表的数据来源于两个不同的数据集 ds1 和 ds2,「销售员」字段是这两个数据集共有的字段,我们使用这个字段建立起他们之间的联系。
选中并双击 D4 单元格,弹出数据列对话框,选择过滤。给单元格增加一个普通条件,将 ds2 的销售员字段与 ds1 的销售员字段进行绑定,实现两个数据集之间的关联。如下图所示:
2.3.1.3.4.2 图表设计
图表的作用在于可以更加直观地表现数据,提升用户的报表查看体验。我们在这张报表中插入柱形图来直观化展示各销售员每个产品的销售总量。
合并A7~D18单元格,选择菜单栏「插入>单元格元素>插入图表」。如下图所示:
弹出图表类型选择对话框,这里选择「柱形图>柱形图」,点击确定。如下图所示:
选中图表,在右边属性面板选择「单元格元素>数据」,设置柱形图的数据。如下图所示:
数据来源:单元格数据
分类名:=B4
系列名:=C3
值:=C4
注:分类名、系列名、值在设置的时候必须要有等号,否则单元格会被作为字符串处理。
柱形图是对表格中地区销售概况数据的图形化展示,所以无需再次设置标题,我们在图表样式中去掉柱形图的标题。
选中图表,在右边属性面板选择「单元格元素>样式>标题」,不勾选标题可见。如下图所示:
这里柱形图展示的是所有销售员的产品销量统计信息,所以不需要对图表所在的单元格进行扩展。
选择图表,在右边属性面板选择「单元格属性>扩展>基本」,扩展方向设置为不扩展,左父格和上父格均设置为无。
注:原理上,此处只需设置上父格为无即可。但为了方便记忆,建议将两个父格均设置为无。
父子格
父子格是跟单元格扩展息息相关的概念,单元格的扩展是针对具体的某一个单元格,当报表主体中绑定了多个单元格时,这些单元格在扩展时是否存在联系,其扩展方向是否会相互影响呢?
以「地区」和「销售员」这两个字段为例,这两个字段之间存在层级关系,每个地区下面会有多个不同的销售员。我们希望这两个字段在单元格扩展时,能够表现出他们之间的层级关系,也就是让这两个字段的数据能够分组展示。FineReport 使用父子格设置来实现这种效果。
图示中「地区」字段为父格,「销售员」字段为子格。设置方法在下面的示例中详细说明。
FineReport 支持两种类型的父子格设置。
左父格:单元格之间存在纵向扩展的关系时,设置左父格。
上父格:单元格之间存在横向扩展的关系时,设置上父格。
用户可以自定义柱形图中系列的柱形颜色,下面我们将系列一的柱形颜色从蓝色修改为紫色。
选中柱形图,点击属性面板「单元格元素>特效>条件显示>添加条件」,双击条件修改条件名为「系列1柱形紫色」,点击「条件编辑」按钮,在弹出的条件编辑对话框中,点击按钮,新增配色属性,下拉框选择紫色,设置普通条件系列序号等于1,点击「增加」按钮。即实现系列一柱形颜色的改变。如下图所示:
保存报表并查看效果
2.3.1.3.4.3 参数设计
参数的作用在于通过设置参数,可以在参数面板中给参数添加控件,再将控件与报表数据进行绑定,进而实现根据用户输入的参数查询指定的数据。
菜单栏选择「模板>模板参数」,打开模板参数设置对话框。如下图所示:
模板参数对话框点击「增加」按钮,新建一个模板参数,双击该参数将它重命名为「地区」,设置默认值为「华东」。点击「确定」完成模板参数的定义。如下图所示:
点击参数面板的编辑按钮,进入参数面板设置界面。如下图所示:
右上角控件设置面板会显示没有添加控件的参数,点击地区或者点击全部添加,将参数的默认控件添加到参数面板。
点击自定义控件的编辑按钮,选择下拉框控件类型。
选中下拉框控件,在右边的控件设置面板选择「属性」,点击数据字典「编辑」按钮,类型设置为「数据库表」,数据库为「FRDemo」,选择数据库表为「销量」,列名的实际值和显示值为「地区」。
这样就给下拉框控件绑定了数据库销量表中的地区这个字段,这个字段下有两个地区信息,分别为华东和华北,用户可下拉选择华东或者华北来查询对应地区下的销售概况信息。
再次点击参数面板的编辑按钮,完成参数控件的设置。
设置好控件后还不能实现根据下拉框中的参数查询指定地区的表格和柱形图信息。因为数据集中的数据是将数据库中的数据全部取出来,表格的数据来源于数据集,柱形图的数据来源于表格,所以需要给表格设置数据过滤条件,当用户下拉选择地区参数点击查询时,表格和柱形图只显示该地区的数据。
双击 A4 单元格,在弹出的数据列对话框中选择「过滤」,添加一个普通条件,让地区等于参数 $地区 ,点击「增加」按钮,点击「确定」。即将地区单元格与参数绑定起来,当下拉框选择地区参数查询时只显示该地区下的表格和图表信息。如下图所示:
2.3.1.4 报表预览
报表必须先保存才能预览,点击「保存」按钮保存报表,点击「预览」按钮,选择「分页预览」,即可在浏览器中查看报表。如下图所示:
浏览器中报表效果如下图所示:
2.3.1.5 报表部署
点击服务器,选择报表平台管理,进入到数据决策系统,进行报表部署。
注意: 首次登录决策系统需要设置管理员账号
账号:admin或root 密码:123456 即可
点击管理系统,创建test目录,将报表放在此目录下。点击添加模版,部署报表。
选择创建的报表路径,点击下一步,然后确定即可。
业务人员就可以通过数据决策系统,查看需求报表数据。
2.3.2 填报报表
2.3.2.1 示例效果
新增数据
修改数据
删除数据
2.3.2.2 数据准备
2.3.2.2.1 数据连接
点击 服务器,选择 定义数据连接
点击 +, 选择 JDBC
配置mysql数据库连接信息,连接的是node1虚拟机中的mysql数据库
出现中文乱码问题, 需要在URL后添加以下信息
?useUnicode=true&characterEncoding=UTF-8
2.3.2.2.2 数据集
在mysql数据库中创建 product 表,并插入几条数据
– 创建商品表
CREATE TABLE product
(
pid INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘商品id’,
pname VARCHAR(20) COMMENT ‘商品名称’,
price DOUBLE COMMENT ‘商品单价’,
category_id VARCHAR(32) COMMENT ‘商品类别id’
);
– 插入数据
INSERT INTO
product(pid, pname, price, category_id)
VALUES
(1, ‘联想’, 5000, ‘c001’),
(2, ‘杰克琼斯’, 800, ‘c002’),
(3, ‘香奈儿’, 600, ‘c003’);
在FineReport中新建数据集 ds1, 数据库查询对话框中写入SQL查询语句,取出product表中的数据
点击 +, 选择 数据库查询
选择查询的数据库,输入sql查询语句,预览验证是否有数据,没问题的话就点击确定
2.3.2.3 报表设计
A1~D1 单元格写入表格标题信息,选中 A1~D1 单元格,右边属性面板中选择 单元格属性>样式, 样式下拉框选择 预定义样式, 给标题设置一个 Head 类型的样式。
将数据集中的相关数据列按照标题字段依次拖入到 A2~D2 单元格,选中 A2~D2 单元格,将字体居中。选中A1~D2 单元格,给表格整体添加内外边框。
2.3.2.4 添加填报控件
给单元格添加录入数据的控件,根据实际应用场景选择填报的控件类型,这边以文本控件为例。
选中 A2~D2 单元格,右边属性面板选择控件设置,选择控件下拉框选择文本控件。根据实际应用场景设置控件属性。
2.3.2.5 设置填报属性
设置填报属性的目的是为了将需要录入数据的单元格跟数据库表中的字段对应起来,确定这个单元格中录入的数据该写入到哪个数据库表下的哪个字段中。
菜单栏选中 模板>报表填报属性,打开报表填报属性设置对话框。
报表填报属性设置对话框选择提交,点击+,新增一个内置SQL的数据提交方法。选择提交类型为智能提交,数据库为node1_mysql,表为product。点击智能添加字段,获取表中的所有字段。
点击智能添加单元格,将数据列对应的单元格值添加到值列(在对应位置直接点击A2~D2单元格自动添加,不要手写),将单元格与数据库表中的数据列绑定起来,勾选pid为主键,勾选未修改不更新,点击确定,即完成报表填报属性的设置。
注1:勾选了 未修改不更新 后,进行填报时,页面上未修改的数据不会参与提交。
注2:如果涉及到修改或删除需求,那么必须勾选一个或多个主键,这里的主键相当于 SQL 中 where 的效果,不同于数据库的主键。
2.3.2.6 设置模板web属性
设置模板 Web 属性的目的是为了自定义填报预览的页面,包括工具栏、报表显示位置、标签页显示位置等等。
注:设置模板 Web 属性不是填报模板制作的必要流程,也可直接使用默认的Web属性设置。
菜单栏选择模板>模板Web属性,打开模板 Web 属性设置对话框。
模板 Web 属性设置对话框中选择填报页面设置,为该模板单独设置填报页面的 Web 属性。勾选填报当前编辑行背景设置,设置其背景色。删除默认的顶部工具栏,从下方的工具库中通过双击的方式将控件添加到顶部工具栏,示例中添加的四个自定义控件分别为:提交、数据校验、插入记录、删除记录。其余选项采用默认设置,点击确定,即完成填报预览页面属性的设置。
2.3.2.7 效果预览
点击保存按钮,保存报表。点击预览按钮,选择填报预览查看报表。
新增数据,点击增加记录,增加新的数据,然后点击数据校验,校验成功点击提交,product表中就会新增此条数据。
修改数据,直接在对应数据行修改数据,然后点击数据校验,校验成功点击提交,product表中就会修改此条数据。
删除数据,选中要删除的数据行,点击删除列行,然后点击数据校验,校验成功点击提交,product表中就会删除此条数据。
移动端预览时,不会显示填报工具栏,所以报表在移动端填报预览时,不能新增和删除数据,只能修改数据。如果想在移动端实现新增和删除效果,可在报表设计时添加插入删除行按钮
插入行按钮,指定单元格修改为A2
删除行按钮,指定单元格修改为A2
填报预览
移动端预览,登录管理员账号密码即可查看操作
2.3.2.8 报表部署
点击服务器,选择报表平台管理,进入到数据决策系统,进行报表部署。
点击管理系统,创建test目录,将报表放在此目录下。点击添加模版,部署报表。
选择创建的报表路径,点击下一步,类型修改为填报,点击确定。
业务人员就可以通过数据决策系统,查看需求报表数据。
2.3.3 决策报表
2.3.3.1 报表效果
现在我们想制作一张如下决策报表,如何实现呢?
参数界面:通过下拉框控件选择地区,查询出对应地区的数据。
报表块:展示参数查询的地区下,各销售员对应的产品类型的销量。
图表块:展示参数查询的地区下,各销售员对应的产品类型的销量图解。
2.3.3.2 报表制作
新建决策报表
菜单栏点击「文件>新建决策报表」,新建空白模板,新建模板步骤如下:
数据集准备
新建数据库查询 ds1 ,输入 SQL 查询语句:SELECT * FROM 销量 ,取出「销量」表中的所有数据。
拖入组件
调整布局
选中 body,此时可以修改组件间隔和内边距,我们将其均修改为 20 。如下图所示:
模板参数
点击菜单栏「模板>模板参数」,新增一个参数,双击参数名重命名为「地区」,默认值输入「华东」。如下图所示:
选中参数界面,将地区参数添加到参数界面,设地区参数的控件为「下拉框控件」。操作步骤如下图所示:
选中下拉框控件,在右侧属性面板中设置「数据字典」,绑定当前模板的数据查询 ds1 中的「地区」字段。如下图所示:
选中参数界面「para」,可设置参数界面的属性,「点击查询前不显示报表内容」默认勾选,那么预览模板时需要点击查询后才显示数据。本例将其取消勾选,预览时则可以直接显示数据。如下图所示
报表块
选中报表块,点击右上角的编辑按钮,进入报表块编辑界面,设计表格如下图所示:
具体操作步骤如下:
1)A1~D1 单元格输入表头信息,将数据集 ds1 中对应的数据列拖入 A2~D2 单元格。
2)选中 A1~D2 单元格,设置字体大小、排列方式、边框、背景等。如下图所示:
选中 D2 单元格,设置「销量」的数据设置为「汇总>求和」。如下图所示:
双击 A2 单元格,设置过滤条件,使其根据「地区」参数过滤数据进行展示。如下图所示:
完成表格设置后,点击界面下方的「表单」回到决策报表 body 界面。
选中报表块,设置报表块组件的标题可见,输入标题「销量明细」。如下图所示:
此时预览模板,效果如下图所示:
图表块
选中图表块,设置组件标题为「销量概况」。如下图所示:
点击图表块右上角的编辑按钮,进入编辑状态,绑定图表数据如下图所示:
预览模板,效果如下图所示:
设置PC端自适应属性
可以看到表格的字体与整体对比,显得略微小了一些,这是因为决策报表的 PC端自适应属性 默认字体是自适应的,会根据浏览器分辨率进行缩放。那么我们点击菜单栏「模板>PC端自适应属性」,选择「为该模板单独设置」,将字体设为不自适应即可。如下图所示:
保存最终的模板,点击「PC端预览」,效果如下图所示:
2.3.3.3 报表部署
操作参考普通报表部署操作即可~
2.4. 数据准备
2.4.1 数据连接
2.4.1.1 数据连接概述
制作报表前首先需要定义数据来源,实际用户系统最常见的就是数据保存在数据库中,并且在不断更新中,使用数据库数据来制作报表,并且报表内容会随着数据库的更新而更新。
FineReport 中有两种数据连接方式:通过设计器建立数据连接和通过平台建立数据连接,
推荐用户在数据决策系统而非设计器中新建数据连接。
在数据决策系统中建立数据连接
选择服务器>报表平台管理,打开数据决策系统,点击管理系统>数据连接>数据连接管理,选择新建数据连接。
在设计器建立数据连接
打开设计器,在服务器>定义数据连接中定义需要连接的数据库,即可建立需要的数据连接。
如果需要修改数据连接的名称,可以通过双击原名称进入编辑状态进行修改,修改完点击「确定」即可,如下图所示:
2.4.1.2 MySQL数据连接
2.4.1.2.1 放置驱动包
若是 10.0.15 及之后的版本,则跳过此步骤。
因为该数据连接使用 FineReport 自带的驱动包 mysql-connector-java-5.1.49-bin.jar ,不需要单独下载驱动包。
若是 10.0.15 之前的版本连接数据库,需要替换更新驱动包:mysql-connector-java-5.1.49-bin.jar
操作步骤如下:
1)删除C:\software\FineReport_10.0\webapps\webroot\WEB-INF\lib下的 MySQL 连接驱动包:mysql-connector-java-5.1.39-bin.jar或mysql-connector-java-8.0.17.jar。
2)将下载好的驱动包拷贝到C:\software\FineReport_10.0\webapps\webroot\WEB-INF\lib路径下,如下图所示:
3)重启报表服务器。
2.4.1.2.2 新建数据连接
管理员登录数据决策系统,在模板设计器中点击服务器>报表平台管理进入数据决策系统,点击管理系统>数据连接>数据连接管理,点击新建数据连接,在所有选项下选择MySQL,如下图所示:
输入对应的数据连接信息。
测试连接,连接成功后点击保存即可
2.4.1.3 Hadoop Hive数据连接
2.4.1.3.1 放置驱动包
将对应Hive版本的驱动包放到 C:\software\FineReport_10.0\webapps\webroot\WEB-INF\lib 路径下,然后重启报表服务器。以Hive 2.7.5版本为例:
2.4.1.3.2 新建数据连接
启动hadoop
start-all.sh
启动hive的metastore服务
hive --service metastore &
启动hive的hiveserver2服务
hive --service hiveserver2 &
管理员登录数据决策系统,在模板设计器中点击服务器>报表平台管理进入数据决策系统,点击管理系统>数据连接>数据连接管理,点击新建数据连接,在所有选项下选择Hadoop Hive,如下图所示:
点击确定进入数据连接配置页面。
测试连接,连接成功后点击保存即可
2.4.2 数据集
2.4.2.1 数据集概述
数据集是指从数据库中将数据取出来,可直接应用于模板设计的数据展现集合。
按使用范围数据集可以分为服务器数据集,模板数据集两种。
服务器数据集
服务器数据集是对应于整个报表工程的,更换一个模板或新建一个工作簿,仍然可以用服务器数据集中的数据。
点击菜单>服务器>服务器数据集,会弹出服务器数据集界面,所有定义的服务器数据集信息都保存在 FineDB 的 fine_conf_entity 表中。
点击+,服务器数据集可以从数据库、程序数据集、内置数据集、文件数据集、存储过程、关联数据集、树数据集中提取数据,如下图所示:
模板数据集
模板数据集是对应于当前模板的,保存在这个模板的 cpt 文件中,不能与其他模板公用,是私有的。
点击菜单模板>模板数据集,会出现如下界面:
拖拽表至语句输入区域,可快速创建 SQL 查询语句,如下图所示:
2.4.2.2 数据库查询
数据库查询是指从定义好的数据库连接中,也就是数据源中使用 SQL 语句来选择需要的字段,一般是直接对数据源中的数据库表直接进行操作。数据库查询方式可分为:表查询、视图查询、模糊查询三种。
2.4.2.2.1 表查询
点击模板>模板数据集,弹出模板数据集对话框,点击模板数据集窗口的左上角的+按钮,选择数据库查询,然后给数据库查询命名,选择所需的数据连接,如下图所示:
选中查询编辑器,在其中输入 SQL 语句select * from product where pid=${pid}。
这是一个带参数的 SQL 查询,${}为参数的形式,中间的 ID 即参数的名称,点击预览,跳出提示框,输入参数 pid=1 ,结果可以在预览组中看,实际就是执行select * from product where pid=1的 SQL 查询。如下图所示:
注意1:FineReport 数据库查询只支持一条自然 SQL 语句的查询,不支持多个自然 SQL 语句,比如SELECT * FROM A SELECT * FROM B
注意2:create 、drop 等新建表、删除表不在官方支持范围内,官方只支持 select 。
注意3:可以将数据连接中的表直接拖动到查询编辑器中
2.4.2.2.2 模糊查询
在表上方有一块空白搜索框,它们用作模糊查询。例如想要搜索客户相关的表,在搜索框中填入客户二字,则会进行自动搜索进行模糊匹配,如下图所示:
2.5 报表入门
2.5.1 报表类型
2.5.1.1 概述
模板设计是 FineReport 学习过程中的主要难题所在,FineReport 模板设计主要包括普通模板设计、决策报表设计和聚合报表设计三种模板设计类型。
FineReport 三种设计模式相辅相成,完美的满足了用户对各种报表的需求,下面我们来比较一下各种设计模式的缺点与优势。
普通模板:是 FineReport 最常用,用的最多的设计模式,保存的文件类型为 cpt,依靠着单元格的扩展与父子格的关系来实现模板效果,可进行参数查询,填报报表,图表设计等等,但是在分页预览模式下不能在报表主体中展示控件,而且单元格间相互影响,很难保持独立性。
聚合报表:一般适用于一张模板中显示多个独立模块的报表。
决策报表:一般适用于控件的展示,保存的文件类型为 frm,很好的弥补了普通报表分页预览不能展示控件的问题,同时决策报表可以进行自由拖拽设计,自适应页面大小显示,可以更好的在 移动端 展示。
2.5.1.2 普通报表
概述
普通报表可以分为报表主体、参数界面设计、图表应用和填报功能四个部分,这四个部分是 FineReport 普通模板的几大使用方式。
普通报表的特点有:类 Excel 设计界面、无限行列扩展和多 sheet 功能,能轻松实现数据间的各种运算,实现复杂表样、分组交叉、同比环比等功能。
同时普通报表还存在一些不足:局限于规整的格子式报表、不支持局部刷新等。
设计步骤
普通报表设计一般有 6 个步骤,如下图所示:
报表主体设计
报表主体设计是纯粹的数据展示,将需要的数据按照类 Excel 方式展示出来,如下图所示:
普通报表可以按照数据的展示方式以及数据来源进行分类,如下表:
分类 概述
行式报表 行式报表即清单式明细表,对数据进行纵向扩展,将数据展示为一个列表式的表格
交叉报表 交叉报表同时包含数据的横向扩展和纵向扩展
分组报表 分组报表就是将报表中的数据按组展示,即将数据列中相同项合并为一组显示
分页报表 分页报表就是将数据根据实际应用进行分页展示
多数据源报表 多数据源报表是指一张表中的数据来自多个数据源
参数界面设计
参数设计是动态查询数据,在查询栏中可以根据实际情况选择需要展示的数据分类,如下图所示:
图表应用
图表设计是使用图表来展示数据,更加便于用户浏览,如下图所示:
填报功能
填报功能是指录入数据,将数据写入数据库中,如下图所示:
2.5.1.3 聚合报表
概述
聚合报表指一个报表中包含多个模块,每一块都类似一张单独的报表或者一张图表,块与块之间相对独立,互不影响。
聚合报表特点:空白画布式设计界面,每个模块相互独立,专门解决大报表难题,单元格扩展分离,互不影响。
聚合报表还存在一些不足:不支持自适应,单元格扩展分离但组件依旧相互推开。
设计步骤
聚合报表设计一般有 5 个步骤,如下图所示:
新建聚合报表:设计器中菜单栏点击「文件>新建聚合报表」,添加 sheet 可选择添加聚合报表或普通报表,如下图所示:
新建数据集:定义各个组件数据来源。
拖拽组件:将需要的图表组件以及报表类型聚合块拖入设计界面,调整整体样式。
注:多个聚合块之间不相互影响。
设计组件:对组件的内容和属性进行设计,包括组件的类型、数据、样式、特效。
报表预览:设计好之后,点击预览按钮 ,聚合报表支持分页预览、移动端预览。
注:不支持填报预览、数据分析预览。
聚合块的移动方式
选中块进行移动时,只要不放开鼠标,移动的块可以覆盖在其他块上,越过它放到其他空白处,但是如果在移动过程中,在覆盖其他块的时候放开了鼠标,此时块自动回到他原来的位置。如下图所示:
拖入新的组件时,只能拖到空白区域,在非空白区域会提示“禁止块与块之间的重叠”,如下图所示:
当报表中存在两个及两个以上的报表块或组件时,改变其中一个报表块或组件,其他相关的报表块或组件的位置将会发生改变。
例如:同一行的两个图表组件,当改变第一个组件的宽度时,第二个组件的位置将会发生变化。如下图所示:
聚合块间的运算
block1 是聚合块名字,点击聚合块右下角,可拖动聚合块,并在右侧组件设置属性表中,可以查看组件名称。如下图所示:
若想在组件里面获取其他组件单元格的值,例如,在 block2 中获取 block1 中单元格 A1 的值,可直接使用公式:block1~A1,如下图所示:
2.5.1.4 决策报表
概述
决策报表是 finereport 设计器支持的 模板设计类型 其中之一。相比较普通报表和聚合报表,决策报表包含二者所拥有的基础组件,同时组件添加更自由化,允许用户根据自己的需求构建报表的框架,在报表中添加丰富的元素。
由于决策报表自由灵活的设计风格,可以说其专为大屏和移动端而生,用户通过简单的拖拽操作即可制作画面美观、内容丰富的管理驾驶舱,制作在手机、平板等移动设备端查看的敏捷报表。在同一个页面,整合不同的业务数据,完美展示企业的各类业务指标,实现数据的多维度分析。
功能
多屏自适应:响应式布局,PC 端设计,平板、手机、电视、大屏等多类终端自适应
丰富的可视化元素:提供表格、图形、控件等超多可视化组件
多种布局方式:自适应布局、绝对布局、Tab 布局等多种布局方式,拖拽式设计
组件共享复用:组件云端共享和本地复用,帮助用户更快设计出好看报表
组件联动分析:组件之间的联动分析,点击某个组件,关联组件自动触发数据加载
数据监控,定时刷新:后台数据智能检测对比,数据有变更前台及时更新
自动轮播:支持同一个位置轮播显示不同的图表样式,支持多个 Tab 页轮播
设计界面
不同于普通报表的设计界面,决策报表采用了画布式的设计界面。报表主体就像一个空白的画板,用户通过将报表组件拖拽到画板中的方式设计报表。如下图所示:
决策报表组件包括:参数面板、空白块、图表块、控件
设计步骤
决策报表设计一般有 5 个步骤,如下图所示:
新建表单:设计器中菜单栏点击「文件>新建决策报表」,新建一张空白的决策报表。
新建数据集:定义各个组件数据来源。
拖拽组件:从参数面板、空白块、图表块、控件面板中选择想要的组件拖拽到画布式设计主体中,调整决策报表的整体样式。
设计组件:对组件的内容和属性进行设计,包括组件的类型、数据、样式、特效等。
报表预览:决策报表设计好之后,点击「预览」,PC端采用「PC端预览」,移动端采用「移动端预览」。
应用示例
大屏应用
移动端应用
2.5.2 报表预览模式
模板预览就是指在 Web 端查看模板效果,FineReport 提供了多种不同的预览方式,来满足用户的多样化需求。
FineReport 中普通模板总共有 5 种不同的预览模式:分页预览、填报预览、新填报预览、数据分析、移动端预览,如下图所示:
不同的预览方式对应不同的 URL 地址栏和 OP 参数 ,预览方式简介如下表所示:
序号 预览方式 简介 URL 地址栏
1 分页预览 FineReport 的默认预览方式,一般在只需要查看报表数据用于分析的时候使用 http://IP:端口号/webroot/decision/view/report?viewlet=xxx.cpt
2 填报预览 是指在 Web 端预览用来填报数据的模板,一般在只需要录入修改数据的时候使用 http://IP:端口号/webroot/decision/view/report?viewlet=xxx.cpt&op=write
3 数据分析 数据分析模式也可以查看报表,但是其可以对报表结果进行不分页预览及在线分析:排序、二次过滤等 http://IP:端口号/webroot/decision/view/report?viewlet=xxx.cpt&op=view
4 新填报预览 新填报预览,采用了新样式的控件,加载速度快,采用了分页加载 http://IP:端口号/webroot/decision/view/report?viewlet=xxx.cpt&op=write_plus
5 移动端预览 通过扫码直接在手机上展现报表,让用户直观地看到当前设计模板的实际效果 http://IP:端口号/webroot/decision/view/report?viewlet=xxx.cpt&op=mobile
6 PC 端预览 PC 端预览是针对于决策报表设计模式而言的 http://IP:端口号/webroot/decision/view/report?viewlet=xxx.frm&op=form
2.5.2.1 分页预览
2.5.2.1.1 概述
分页预览是 FineReport 的默认预览方式,一般在只需要查看报表数据的时候使用。
2.5.2.1.2 功能简介
打开设计器,双击打开内置的 GettingStarted.cpt 模板,点击设计器界面上的「预览按钮>分页预览」即可预览报表,如下图所示:
点击「分页预览」之后,在浏览器端就会打开一张报表,如下图所示:
功能设置
分页预览设置页面,仅对「分页预览」模板有效。在设计器中点击「模板>模板web属性>分页预览」设置,可对分页预览界面进行设置。如下图所示:
主要功能模块如下:
功能 内容 注意事项
设置方式 默认选择「采用服务器设置」,可选择「为该模板单独设置」 -
报表显示位置 设置报表在浏览器显示的位置 移动端不生效
页面 页面的一些特殊设置 -
工具栏 可设置是否显示工具栏以及自定义工具栏显示的内容 移动端不支持工具栏设置
事件设置 用户可添加 Web 事件 移动端仅支持加载起始和加载结束事件
设置方式
采用服务器设置
设置方式默认为「采用服务器设置」,底部功能均被置灰不可编辑,该方式作用于当前服务器下的所有模板。
如果想要修改服务器预定义的分页预览设置,可以点击设计器菜单栏「服务器>服务器配置」,在打开的「报表服务器参数」界面选择「分页预览设置」进行修改。如下图所示:
为该模板单独设置
设置方式下拉选择「为该模板单独设置」时,可直接编辑下方的功能,配置好的页面只作用于当前模板,其他模板不可用。
报表显示位置
设置报表预览时在浏览器的显示位置,分为「居中展示」和「左展示」,默认为「左展示」,如下图所示:
居中展示
左展示
页面设置
对预览页面的一些特殊设置,如下图所示:
以图片方式显示:分页预览的时候,会生成图片形式的报表。
iframe 嵌入时自动收缩:当模板以 iframe 的方式嵌入到其他的模板当中时,预览时会自动调整模板的大小,以适应 iframe 的大小。
嵌入的模板未勾选「iframe 嵌入时自动收缩」时,效果如下图所示:
嵌入的模板勾选「iframe 嵌入时自动收缩」后,效果如下图所示:
重方式输出格子:控制单元格的行高列宽不随内容多少而变化。
工具栏
显示工具栏
系统默认勾选使用工具栏,即分页预览时上方会显示工具栏,如果需要隐藏工具栏,去掉勾选即可。
添加工具
1 双击工具,将工具添加到顶部工具栏。
2 选中工具后,点击 将工具添加到顶部工具栏,点击 将工具添加到底部工具栏。
3 点击「恢复默认」,可恢复原始状态。
自定义工具栏
点击工具栏右边的 ,即可进入工具栏编辑界面,如下图所示:
编辑界面可以修改已经添加的工具属性和排序,删除单个工具,自定义工具栏的背景。如下图所示:
工具栏背景默认「没有背景」,点击「背景设置」,可设置背景为「颜色」、「纹理」、「图案」、「渐变色」、「图片」。以设置背景「颜色」为蓝色为例,效果如下图所示:
删除工具
删除所有工具:点击工具栏右边的 ,即可清空工具栏中的所有工具,如下图所示:
删除单个工具:点击工具栏右边的 ,在工具栏编辑界面可通过 删除单个工具,如下图所示:
事件设置
点击事件设置下方的 ,可添加 JS 事件,通过 JavaScript 代码的方式实现其他预览需求。
2.5.2.2 填报预览
2.5.2.2.1 概述
填报预览指在 Web 端预览用来填报数据的模板,一般在只需要录入修改数据的时候使用,也可用来查看数据。
2.5.2.2.2 填报预览
填报预览不仅可以用来查看,而且可以在线输入与修改数据,从而进行数据的采集与入库。
1 打开设计器,在模板面板中打开doc/Form/FreeForm/自由填报模板.cpt这张模板,点击预览按钮下方的倒三角,选择「填报预览」,如下图所示:
2 点击「填报预览」按钮之后,就会在 Web 端以填报的方式打开模板,可在 Web 端对模板内容进行编辑修改,进行数据的入库操作,相较于分页预览,填报预览的URL地址后面多了一个&op=write的参数。op参数的值来控制模板的预览方式,没有参数就是普通分页预览,有参数且参数值为 write 就表明这是填报预览。如下图所示:
2.5.2.2.3 填报预览设置
采用服务器设置
设置方式默认为「采用服务器设置」,底部功能均被置灰不可编辑,该方式作用于当前服务器下的所有模板。
如果想要修改服务器预定义的填报预览设置,可以点击设计器菜单栏「服务器>服务器配置>填报预览设置」进行修改。
为该模板单独设置
在设计器中点击「模板>模板web属性>填报页面」设置,就可以对填报页面进行设置,如下图所示:
设置面板主要分为三大块:上面部分是对模板预览效果的一些效果设置,中间部分是模板预览之后的工具栏设置,下方是 Web 事件添加界面。
属性 内容 注意事项
以下设置 采用服务器设置:默认情况,使用服务器统一的设置,下面的所有选项都为灰色无法编辑为该模板单独设置:只适用于当前的模板,下面所有的功能可编辑、设置 -
sheet 标签页显示位置 当报表中存在多个sheet时,sheet标签页位置默认处于报表底端,可设置在报表上部 移动端无意义
报表显示位置 设置内容在报表当中显示的位置默认为左展示,如果希望报表显示的内容是居中的,可以选择居中展示 移动端无意义
填报当前编辑行背景颜色设置 选择颜色后,会在填报预览的时候,把当前处于编辑状态的行背景颜色显示为设置的颜色 移动端无意义
未提交离开提示 在填报的时候,如果有单元格处于已编辑的状态,在关闭或是切换网页的时候,会弹出是否提交的对话框 -
直接显示控件 填报控件无需点击,直接显示控件 移动端无意义
自动暂存 对于填报内容,离开页面时,自动暂存 移动端无意义
使用工具栏底部工具栏 默认使用工具栏用户可自定义工具栏显示的工具 移动端只识别是否要显示填报提交按钮
事件设置 用户可添加 Web 事件Web 事件的详细介绍请参见 Web 页面事件 移动端仅支持加载起始、加载结束、填报前、填报后、填报成功、填报失败事件
2.5.2.3 数据分析预览
2.5.2.3.1 概述
数据分析预览方式可以在查看数据时,对数据进行简单的分析操作,包括:排序、条件筛选、列表筛选。
2.5.2.3.2 功能简介
数据分析预览的方式有两种,分别如下:
按钮:在设计器预览按钮列表下直接选择「数据分析」即可。
后缀:直接在访问模板的URL后面加参数后缀&op=view即可。
注意1:移动端是不支持数据分析预览的。
注意2:数据分析预览时,数据不会分页展示。
数据分析预览设置
设置方式
采用服务器设置
设置方式默认为「采用服务器设置」,底部功能均被置灰不可编辑,该方式作用于当前服务器下的所有模板。
如果想要修改服务器预定义的数据预览设置,可以点击设计器菜单栏「服务器>服务器配置>数据预览设置」进行修改。
为该模板单独设置
点击设计器菜单栏「模板>模板Web属性>数据分析设置」,设置方式下拉选择「为该模板单独设置」时,可编辑下方的所有功能,配置好的页面只作用于当前模板,其他模板不可用。如下图所示:
主要功能模块如下:
功能 内容 注意事项
排序 选中某个单元格,使用排序工具对该单元格所在列的数据进行排序 -
条件筛选 选中某个单元格,设置操作符、数据类型、数值这三个条件,筛选出该单元格所在列的某些数据 -
列表筛选 选中某个单元格,复选该单元格所在列的去重数据列表,只显示勾选的数据 如果前端显示的数据量大于 100 条,那么列表筛选工具就不显示
工具栏 可设置是否显示工具栏以及自定义工具栏显示的内容 移动端不支持
事件设置 用户可添加 Web 事件,详情可参见 Web 页面事件 移动端不支持
排序
排序指选中某个单元格,使用排序工具对该单元格所在列的数据进行排序。默认勾选,效果如下图所示:
条件筛选
条件筛选指选中某个单元格,设置操作符、数据类型、数值这三个条件,筛选出该单元格所在列的某些数据。默认勾选,效果如下图所示:
列表筛选
列表筛选:选中某个单元格,复选该单元格所在列的去重数据列表,只显示勾选的数据。默认勾选,效果如下图所示:
注意事项
无法排序
数据分析预览排序需要把最前面的父格设置为列表(其它列为分组),否则除了最父格,其他无法排序。
不显示列表筛选工具
如果前端显示的数据量大于 100 条,那么列表筛选工具就不显示,这是 FineReport 数据量限制规则决定的。
无法使用分析工具
双向扩展得到的数据,无法使用数据分析工具。
当单元格存在多层父格,且与父格属于同一个数据集,则无法使用数据分析功能。
示例 情况 结果 分析
1 单元格 C1 的父格是 B1单元格, B1 的父格是 A1单元格, A1 无父格, 单元格 A1、B1、C1 是一个数据集 单元格 A1、B1 有数据分析功能单元格 C1 没有 单元格 C1 的父格层级是 2且父格 A1、B1 与 C1 是同一个数据集
2 单元格 C1 的父格是 B1单元格, B1 的父格是 A1单元格, A1 无父格,单元格 A1、B1 是一个数据集,单元格 C1 是一个数据集,通过过滤和单元格 A1、B1关联起来的 单元格 A1、B1、C1 都有分析功能 -
3 单元格 E1 的父格是 D1单元格, D1 的父格是 C1单元格, C1 的父格是 B1单元格, B1 的父格是 A1单元格, A1 无父格,单元格 A1、B1 是一个数据集,单元格 C1、D1、E1是一个数据集,通过过滤和 A1、B1关联起来的 单元格 A1、B1、C1、D1 有分析功能单元格 E1 没有 单元格 E1的父格层级是2且父格 C1、D1 与 E1 是同一个数据集
2.5.3 单元格设置
2.5.3.1 扩展性
2.5.3.1.1 扩展的方向
扩展是有方向的,您可以选择记录是依次从上至下的显示,即纵向扩展(行方向的扩展);或者是依次从左到右的显示,即横向扩展(列方向的扩展);当然你也可以选择不扩展,在一个单元格中显示。
纵向扩展
横向扩展
不扩展
2.5.3.1.2 父格设置
子格的扩展属性会随着父格的扩展属性变化,当单元格左侧或上方相邻的单元格具有扩展属性时,单元格默认其左侧相邻单元格为其左父格,默认上方相邻的单元格为其上父格。
父格的设置有 3 种:不设置,默认设置和自定义设置,如下图所示:
对于自定义设置,可以自己输入父格或者点击下图的按钮,点击想要的单元格,它会自动返回单元格的行和列,如下图所示:
2.5.3.1.3 可伸展性
有时我们会遇到:可扩展的单元格其左侧的单元格,并不会像普通的插入那样按常态分为新的行,而是整体被拉大的效果。即展示单元格中的内容时是不伸展展示,且要让其不随子格或同级别单元格的扩展而被拉大。对于单元格的可伸展性,可分为:纵向可伸展性与横向可伸展性。下面就对其单元格的横向伸展性作简单介绍。
如:
图中可见,上面的单元格数据,均是随中间部分的数据都被拉大了,而这时希望上侧的单元格,不受其中间的单元格内容影响,则可选中不需要受影响的单元格,在报表主体右侧的单元格属性-扩展-高级中取消横向可伸展的勾选即可:
效果图如下:
2.5.3.2 父子格设置
2.5.3.2.1 功能介绍
FineReport 设计报表时,选中单元格后,单元格的父格会有「蓝色箭头」。如下图所示:
FineReport 支持两种类型的父子格设置。
左父格:单元格之间存在纵向扩展的关系时,设置左父格。
上父格:单元格之间存在横向扩展的关系时,设置上父格。
2.5.3.2.2 应用场景
父子格是跟单元格扩展息息相关的概念,单元格的扩展是针对具体的某一个单元格,当报表主体中绑定了多个单元格时,这些单元格在扩展时是否存在联系,其扩展方向是否会相互影响呢?
以「地区」和「销售员」这两个字段为例,这两个字段之间存在层级关系,每个地区下面会有多个不同的销售员。我们希望这两个字段在单元格扩展时,能够表现出他们之间的层级关系,也就是让这两个字段的数据能够分组展示。FineReport 使用父子格设置来实现这种效果。
图示中「地区」字段为父格,「销售员」字段为子格。设置方法在下面的示例中详细说明。
2.5.3.2.3 示例
在设计器中设置子格的左父格或上父格时,下拉框有三种设置项:「无」,「默认」,「自定义」。
下面以单元格纵向扩展时设置左父格为例,详细介绍父子格设置时三种设置项各自的应用场景和效果。
无
「无」就是不设置单元格的父格,该单元格扩展时不考虑单元格之间的分组关系。
选中 B2 单元格,右边属性面板选择「单元格属性>扩展」,扩展方向采用默认设置「纵向扩展」,左父格设置为「无」。
报表效果如下图所示:
默认
当单元格左侧或上方相邻的单元格具有扩展属性时,单元格默认其左侧相邻单元格为其左父格,默认上方相邻的单元格为其上父格。
「默认」就是指将数据列拖拽至单元格中时,该单元格会默认将其相邻上方横向扩展的单元格或者左侧纵向扩展的单元格当做上父格或者左父格。
注意1:必须是相邻的同行或者同列单元格,不是相邻的需要自定义设置。
注意2:其单元格的左侧相邻单元格不具有扩展属性时,会依次向左或向上寻找具有扩展属性的单元格,来确定它的父格。
选中 B2 单元格,右边属性面板选择「单元格属性>扩展」,扩展方向采用默认设置「纵向扩展」,左父格设置为默认。由于 B2 左侧单元格 A2 是纵向扩展的,因而 B2 单元格默认的左父格为A2。
报表效果如下图所示:
自定义
单元格之间存在扩展关系,但是它们不相邻无法使用默认设置时,通过「自定义」来设置它们之间的父子格关系。
A2 单元格和 B3 单元格不相邻,但是它们之间仍然存在纵向扩展的层级关系。选中 B3 单元格,右边属性面板选择「单元格属性>扩展」,扩展方向采用默认设置「纵向扩展」,左父格自定义为 A2 单元格。
报表效果如下图所示:
2.5.3.3 单元格扩展
2.5.3.3.1 功能介绍
FineReport提供了三种单元格扩展方向。
纵向扩展:单元格中字段的数据纵向扩展,在不同单元格中展示。
横向扩展:单元格中字段的数据横向扩展,在不同单元格中展示
不扩展:单元格中字段的数据不扩展,所有数据在一个单元格中展示。
2.5.3.3.2 应用场景
数据集中的字段拖入到单元格后,如果不进行单元格扩展,字段下的数据会在一个单元格中集中展示。
通过设置单元格扩展功能,可以让一个字段下的不同数据在多个单元格中展示。
2.5.3.3.3 示例
数据准备
新建数据集 ds1,数据库查询对话框中写入 SQL 查询语句:SELECT * FROM 销量,取出「销量」表中的所有数据。如下图所示:
将数据集 ds1 中的「销售员」字段拖入到A1单元格,A1单元格字体居中,添加黑色边框和黄色背景。如下图所示:
纵向扩展
选中 A1 单元格,右边属性面板选择「单元格属性>扩展>扩展方向」,由于数据集中的字段拖入到单元格后,默认就是纵向扩展,所以直接使用默认的扩展方向纵向扩展。如下图所示:
点击「预览」按钮,选择「分页预览」,在浏览器中查看单元格纵向扩展的效果。如下图所示:
横向扩展
选中 A1 单元格,右边属性面板选择「单元格属性>扩展>扩展方向」,扩展方向设置为「横向扩展」。如下图所示:
点击「预览」按钮,选择「分页预览」,在浏览器中查看单元格横向扩展的效果。如下图所示:
不扩展
选中 A1 单元格,右边属性面板选择「单元格属性>扩展>扩展方向」,扩展方向设置为「不扩展」。如下图所示:
点击「预览」按钮,选择「分页预览」,在浏览器中查看单元格不扩展的效果。如下图所示:
2.5.3.4 单元格样式
2.5.3.4.1 概述
选中单元格,在右侧选择「单元格属性>样式」,可设置单元格自定义样式或预定义样式,如下图所示:
注意:样式只控制单元格的显示效果,对单元格的实际值没有影响。
2.5.3.4.2 自定义样式
选中单元格后,点击「单元格属性>样式」,默认设置为自定义样式,用户可对文本样式、单元格样式和对齐方式进行设置,如下图所示:
2.5.3.4.2.1 文本
格式
可对数字、时间等数据,设置显示格式,如下图所示:
数字样式
格式符 定义 示例
0 占位格式符,不足补 0 格式:0.0实际数据:1、2.2、3.33显示数据:1.0、2.2、3.3
占位格式符,不足不补 0 格式:0.#实际数据:1、2.2、3.33显示数据:1、2.2、3.3
设计器中内置的一些常用格式,如下图所示:
用户也可手动编辑,自定义相关格式,例如:
格式:#0.0m
实际数据:1、2.2、3.33
显示数据:1.0m、2.2m、3.3m
货币样式
货币部分 ¤0 表示在整数前面加一个¥,其 ¤#,##0.00 跟数字部分原理类似。
百分比样式
百分比中,可选择显示小数后多少位,也可以自己进行添加位数以及其他字符。如下图所示:
注意:百分比样式中,取小数位数时,遵循奇进偶不进规则。
日期型样式
日期型中可以设置日期的显示样式,例如希望日期型的数据显示成「20110101」这样的格式,则设置样式为「yyyyMMdd」即可,日期样式如下图所示:
注意1:月份必须为大写的 M ,小写的 m 无法识别。
注意2:设置日期格式时可手动输入。
字体
字体部分设置可以选择字体类型、字形、字体大小、颜色、下划线、删除线、阴影、上下标。其中上下标默认为既无上标也无下标,如下图所示:
注意1:由于 Chrome 浏览器的限制,在 Chrome 浏览器下查看报表,最小字体为 9,就算设置了更小号的字体也会显示为 9。
注意2:IE 浏览器 10 及 11 版本支持阴影效果,其余版本不支持阴影效果。
2.5.3.4.2.2 单元格
边框
对于单元格的边框,可设置内外边框的线条样式和颜色。如下图所示:
注意:单元格设置边框后,最终显示效果和浏览器渲染方式有关,同一设置,不同的浏览器可能会表现出不同的效果。
用户也可点击工具栏上的边框按钮,对单元格边框进行自定义设置,如下图所示:
背景
单元格背景可以选择纹理和图片以及设置颜色
2.5.3.4.2.3 对齐
基本对齐
对齐方式是指单元格中文本的对齐方式,可分别设置水平对齐和垂直对齐方式,如下图所示:
水平对齐:靠左、居中、靠右、分散对齐、默认。默认数字右对齐,非数字左对齐。
垂直对齐:靠上、居中、靠下。默认居中。
高级对齐
1 图片布局
单元格内容为图片时,可设置图片布局为:默认、平铺、拉伸、适应,如下图所示:
2 文本控制
单元格文本控制格式有四种:自动换行、单行显示、单行显示(调整字体)、多行显示(调整字体)。如下图所示:
方式 定义 示例
自动换行 不调整字体大小根据单元格大小显示,显示不完就自动换行
单行显示 不调整字体大小根据单元格大小显示,显示不完就不再显示
单行显示(调整字体) 调整字体大小默认一行显示完所有文字
多行显示(调整字体) 调整字体大小默认多行显示完所有文字
注意:单元格必须已设置自动调整行高,再设置自动换行才有效果的。仅设置自动换行是没有效果的。
3 文本方向
文字排列方式有三种:自定义角度、文字竖排(从左向右)、文字竖排(从右向左),如下图所示:
注意1:除了自定义角度为 0 时,其他情况下,浏览器端预览时,单元格内容以图片格式显示。
注意2:特殊字符也能实现文字竖排。
4 缩进
用户可设置单元格文字左右缩进距离,默认左右各缩进 2px。如下图所示:
5 间距
用户可设置单元格段前间距、段后间距、行间距,如下图所示:
段前间距:单元格内文字的段前距。
段后间距:单元格内文字的段后距。
行间距:单元格内每行文字之间的距离。
预定义样式
选中单元格后,点击「单元格属性>样式」,选择预定义样式,即可显示出设计器内置的所有预定义样式,如下图所示:
注意:FineBI 工程未内置预定义样式,所以设计器远程连接 BI 服务器时,没有工程自带的预先定义好的样式。
2.5.3.5 数据显示方式
2.5.3.5.1 功能简介
在客户端的浏览器中,查看报表的效果都是通过对基础数据进行加工而来的。制作一张报表模板,首先需准备报表所需的基础数据。基础数据的来源方式有多种,可来源于数据库表、视图、存储过程,或是其他文本文件如Excel等等,详细请查看 数据集 ,不管数据来源于哪种方式,经过哪些预处理,最终都是返回如下图所示的一张或是多张二维表:
拥有了这些基础数据后,我们就可以对这些数据进行再加工,让其显示出我们所需的样式。其数据的显示方式有三种分别为:列表、分组、汇总,如下图:
2.5.3.5.2 列表
如上图,制作的报表展示出来的数据与数据集数据完全相同,即数据集中的每条记录无论是否重复都原封不动的展示出来,此为清单式明细列表。 在设计器中的设置方式如下:
可看到设为列表的数据列,以“S”表示,其对应英文 select。
2.5.3.5.3 分组
分为普通分组、相邻连续分组和高级分组,如下我们对比看下三者使用的不同情景。
普通分组
如上图所示,将数据列中相同项合并为一组显示的方式,我们称为分组显示。
设计器中的设置方式如下:
相邻连续分组
像这样只有连在一起的相同数据才进行合并的方式,我们称为相邻连续分组。
设计器中的设置方式如下:
该分组方式的优点为:它一般是配合 SQL 中已排好序的列,对其实现的分组,这样实现的分组性能比普通分组会好一点,可解决分组慢的问题。
高级分组
高级分组又分条件分组和公式分组,点击自定义出现如下界面:
2.5.3.5.3 汇总
对于表中的数值类型字段,我们可以设置其聚合方式,如:可以对销量字段,根据地区与销售员进行汇总求和;或计算出某地区某销售员所有产品的平均销量、最大销量、最小销量、产品个数等等。这些都属于数据的汇总。
在设计器中的设置如下对销量进行数量汇总:
并将 E2单元格的父格设置为 B2,销量就可以按照销售员进行求和,如下:
预览效果如下图所示:
2.5.3.6 数据列属性
2.5.3.6.1 概述
当单元格内容为数据列时,选中单元格,右侧「单元格元素」面板就会出现数据列属性设置框,或者双击单元格也可弹出数据列属性设置对话框,如下图所示:
2.5.3.6.2 基本
数据列的基本属性包括「选择数据列、父格设置、数据设置、扩展方向」四类设置,如下图所示:
选择数据列
「选择数据列」就是指将数据集中的字段与单元格绑定,在参数绑定数据列 章节中描述了通过拖曳的方式选择数据列,这里我们是通过下拉框选择来选择数据列,如下图所示:
父格设置
父格设置就是指父子格设置 ,既可在扩展属性中设置,也可以在数据列基本设置中设置,操作方式都一样。
数据设置
数据设置就是指修改数据显示方式。
扩展方向
扩展方向就是指扩展属性中的可伸展性,分为纵向扩展、横向扩展和不扩展。
2.5.3.6.3 过滤
选中单元格,选择报表主体右侧「单元格元素」面板中的「过滤条件>编辑」按钮或者双击单元格,选择过滤,就可以设置单元格的过滤条件,如下图所示:
父格条件
默认选中「将父格子作为过滤条件」,适用于父子格来自于同一个数据集。
将父格作为过滤条件意味着在满足当前单元格条件的同时首先要以父格为条件,子格将继承父格的过滤条件,即如果父格设置了过滤,子格不需要再设置相同条件的过滤。
普通条件
「普通条件」即对该单元格所在数据集的数据列定义过滤条件,只有某个数据列满足条件时,当前单元格的数据才会被选出来。
其中过滤条件由「可选列」、「操作符」、条件 组成,可以为各种形式,用户根据不同需要设置即可。「可选列」为当前单元格数据列所在的数据集的所有数据列,操作符为一些文字化的运算符,条件支持多种形式。如下图所示:
在制作报表时,若因某种需要使得数据集中的某些数据列无数据列名(即字段名为空),而这数据列拖入报表中展示数据是无影响可以正常显示数据的。但若该字段名为空且要作过滤时,设置过滤后,发现其过滤条件却是是无效的,此时可选择「列序号」作为「可选列」的条件,如下图所示:
条件中除一些如字符串、整型、日期等数据类型外,还包括公式、单元格、参数、数据列,其中公式、单元格、参数比较常见,数据列是指当前模板可用的所有数据集中的数据列。选择数据列,即需要满足的条件值为数据列中的所有值,当是多个值时,就以多个值过滤。
公式条件
若不是对数据列添加过滤条件,或者需要对数据列进行操作后再设置过滤条件,此时可以使用「公式条件」。
点击定义,出现公式编辑页面,如下图:
2.5.3.6.4 高级
选中单元格,选择报表主体右侧「单元格元素」面板中的「高级」或者双击单元格,选择高级,就可以对单元格进行高级设置,如下图所示:
排列顺序
设置数据列的排列顺序,包括「升序、降序、不排序」三种情况。
结果集筛选
设置结果集的显示,如显示前 N 个、后 N 个等。
自定义显示
自定义显示单元格的值,如可以输入 FineReport 公式修改单元格的显示值。默认值为「$$$」,代表单元格本身的值。
数据库中存储的数据为「FR 帆软软件」,将数据列拖曳至 A1 单元格。
双击 A1 单元格,选择高级,在自定义显示中插入公式:replace($$$,“FR”,“FineReport”),将 FR 替换为 FineReport,如下图所示:
保存模板,点击「分页预览」,数据显示为「FineReport 帆软软件」,如下图所示:
注意:如引用该单元格值,引用的自定义显示后的值,而非原实际值。
例:A1 单元格的实际值为「FR 帆软软件」,自定义显示后的值为「FineReport 帆软软件」,B1 单元格引用 A1 单元格的值为「FineReport 帆软软件」。
可伸展性
数据的伸展性,分为「横向可伸展」和「纵向可伸展」。
补充空白数据
补充空白数据,可以设置数据倍数,例如设置数据倍数为 10,不足 10 条的数据会自动补足到 10 条。如下图所示:
2.5.3.7 数据列常用过滤条件
2.5.3.7.1 过滤条件中使用nofilter
nofilter 的含义为不过滤,通常用于某个条件不成立的情况下过滤条件无效。
if(len( a r e a ) = = 0 , n o f i l t e r , area)==0,nofilter, area)==0,nofilter,area) 表示参数 area 为空,则不过滤,若不为空则以参数值进行过滤。如下图所示:
2.5.3.7.2 对某一列进行处理后再过滤
通常用于某列值比较特殊,截取该列的值中的某一部分进行过滤的情况。
比如我们要设置过滤订单 ID 前三位为103,可以使用 left(订单ID,3)= 103,意为从左边开始截取前三位等于 103 的值,在公式中可以直接使用列名,如下图所示:
2.5.3.7.3 过滤条件的与或
通常用于根据不同的情况使用不同的过滤条件。
例如:货主地区等于 area and 货主省份等于 province and 货主省城市等于 city ,当三个过滤条件都满足时过滤数据,如下图所示:
当货主地区为华东,货主省份为山东,货主城市为青岛,查询数据如下图所示:
2.5.4 参数应用
2.5.4.1 参数入门
2.5.4.1.1 参数简介
参数指在设置或赋值不同的数值来实现一个目标结果,这些数值就是参数。为满足不同客户的使用需求,FR 设计器中引入了参数的概念。在FR设计器中使用参数动态地过滤数据,实现用户与数据的实时交互。
参数可实现功能如下:
参数查询:指需要获取不同条件下数据。例如查询某地区的销售额,那么“地区”就可以作为一个参数来使用,传入不同的地区,就会有不同的结果展现出来。
实现参数查询步骤:
定义参数:设置参数名称,添加参数,根据实际应用场景的需要选择不同类型的参数。
参数添加控件:控件是参数实现查询的载体,选择控件类型,通过将控件和参数绑定,实现在控件中输入参数值,能够过滤并查询出用户想要查看的数据。
设置参数面板样式:通过设置参数界面中控件的位置,参数面板的位置,背景色等等来改变控件栏的展示效果。
2.5.4.1.2 参数面板
2.5.4.1.2.1 组件设置
新建一张普通报表,进入参数面板,参数面板的属性如下图所示:
属性
「属性」Tab 下,参数面板的各设置项介绍如下表所示:
设置项 说明
组件名称 可自定义组件名称
标签名称 可自定义标签名称
背景 参数的默认背景色为灰色用户若需要参数界面的风格和报表风格相同或达到其他效果,可自定义参数面板的背景,其效与 纸张背景 效果相同
点击查询前不显示报表内容 1)勾选「点击查询前不显示报表内容」按钮在定义参数的情况下,直接预览则不显示报表,需要用户手动点击「查询」按钮,查询报表。2)不勾选「点击查询前不显示报表内容」按钮需给参数设置默认值,取消勾选「点击查询前不显示报表内容」按钮,点击预览,即可自动使用参数的默认值进行首次查询并展示报表。 注:设置「点击查询前显示报表内容」的同时要给参数设置默认值,否则在首次展示时会根据空值进行过滤
显示位置 参数界面的显示位置可以设置为靠左、居中以及靠右显示注:参数界面的显示位置以参数界面的宽度来靠左、靠右或者居中,而不是浏览器的页面宽度
尺寸 可自定义参数面板的设计宽度注:在参数面板中添加控件后,若最右侧控件所处的位置横坐标大于要修改的参数面板的「设计宽度」,则修改不成功
事件
参数面板的「事件」Tab 页如下图所示:
事件介绍
可为参数面板添加初始化后事件和点击事件:
初始化后事件:预览模板之后触发。
点击事件:是点击参数面板任意地方之后触发。
初始化后事件示例
新建普通报表,参数面板中添加「下拉框控件」,参数面板添加「初始化后事件」,如下图所示:
JavaScript 如下所示:
alert(“123”)
保存模板,点击「分页预览」,如下图所示:
2.5.4.1.2.2 调整参数界面大小
调整高度
在参数界面面板中,可以设置参数在 B/S 端的高度,如下图所示:
灰色部分为参数界面的边界,可以通过拖动灰色部分来调整参数界面的高度。
调整宽度
从属性表里面调整参数界面的宽度,默认设计宽度为 960,如下图所示:
2.5.4.1.2.3 隐藏参数面板
参数面板在预览时,可点击「显示隐藏按钮」对参数面板进行隐藏,如下图所示:
若用户需要整个参数面板完全隐藏(包括小箭头),在 URL 后面拼接参数 &pi=false,刷新预览,如下图所示:
注意:使用此方法后,普通报表将无法获取到给参数面板中控件赋的默认值。
2.5.4.1.3 参数分类
2.5.4.1.3.1 模板参数
概述
模板参数是只适用于当前报表的参数,需要与数据列的过滤条件结合使用。先通过数据集取出所有数据,再在报表中设置模板参数,在数据查询时使用模板参数过滤出有用的数据,适用于数据量小的情况。数据量大的情况,建议使用数据集参数进行过滤。
功能简介
文本框中输入「华东」,点击查询,只查询出报表中华东地区的销售信息。
示例
数据集准备
新建数据集 ds1,数据库查询对话框中写入 SQL 查询语句:SELECT * FROM 销量,取出销量表中的所有数据。如下图所示:
表格样式设计
A1~C1 单元格写入表格标题信息,选中 A1~C1 单元格,右侧属性面板选择「单元格属性>样式」,样式下拉框选择「预定义样式」,给标题设置一个「Head」类型的样式。如下图所示:
将数据集中的字段拖入到对应单元格中,选中 A2~C2 单元格,将字体居中,选中 A1~C2 单元格,给表格整体添加预定义样式默认的天蓝色内外框。如下图所示:
选中 C2 单元格,右侧属性面板选择「单元格元素>基本」,数据设置下拉框选择「汇总>求和」。如下图所示:
定义模板参数
菜单栏选择「模板>模板参数」,弹出模板参数设置对话框。如下图所示:
模板参数对话框点击增加按钮,新建一个模板参数,双击该参数将它重命名为「地区」,设置默认值为字符串「华东」。点击确定完成模板参数的定义。如下图所示:
如果想要修改模板参数名称,只能通过双击原名称进入编辑状态后进行修改,修改完后点击「确定」即可,如下图所示:
参数添加控件
点击参数面板的「编辑」按钮,进入参数面板编辑界面。如下图所示:
右上角控件设置面板会显示没有添加控件的参数,点击「地区」或者点击「全部添加」,将参数的默认控件添加到参数面板。如下图所示:
注意:参数与控件是通过参数名称进行绑定的,也就是说当控件名称与参数名称一致时,参数与控件就进行了绑定,即在 Web 端给控件赋值就相当于给参数赋值。
参数「地区」的默认控件添加到参数面板后,效果如下图所示:
注意:如果不想点击「全部添加」或「参数」快捷添加默认控件,也可以直接从控件栏中将控件拖拽到参数面板中,修改控件的名称与参数名称一致,即可将控件与参数进行绑定。
点击自定义控件的「编辑」按钮,选择「文本控件」类型,让用户自行输入参数值。如下图所示:
将查询按钮往左边拖拽,形成紧凑式布局,让控件面板更加美观。再次点击参数面板的「编辑」按钮,完成参数面板的设置。如下图所示:
数据过滤
设置好控件后还不能实现根据文本框中输入的参数值查询指定地区的销售信息。因为表格的数据来源于数据集,数据集中的数据是将数据库表中的数据全部取出来的,所以需要给表格添加「数据过滤条件」,才可以查询出控件输入的参数值的信息。
双击 A2 单元格,在弹出的数据列对话框中选择「过滤」,添加一个普通条件,设置数据列为地区,操作符为等于,值类型修改为参数类型,选择 $地区,点击「增加」按钮,点击「确定」。即将地区单元格与参数绑定起来。如下图所示:
2.5.4.1.3.2 数据集参数
概述
类似通信、监控行业,每天都有海量数据生成,数据库表中总数据量非常大,而报表中往往只要获取当天的几百条数据就可以了。
如果使用模板参数,就需要先取出所有数据,再进行过滤,取数+过滤,将消耗大量时间,极大影响报表的查询效率。而数据集参数在数据库查询时就已经完成了数据过滤,所以使用数据集参数设计的查询报表会比使用模板参数的效率高。
功能简介
定义数据集时,通过在 SQL 语句中添加 p a r a 格式的内容即可定义数据集参数。定义完成后,用 {para}格式的内容即可定义数据集参数。定义完成后,用 para格式的内容即可定义数据集参数。定义完成后,用参数名即可引用,使用方法和模板参数一致。如下图所示,下拉框选择「华东」,点击查询,只查询出报表中华东地区的销售信息。
使用说明
数据集 SQL 查询语句中可以使用参数宏 动态地生成过滤条件, {}动态地生成过滤条件, 动态地生成过滤条件,{} 执行结果与 SQL 语句拼接起来形成最终的查询语句,传递给数据库执行。SQL 语句中可以使用多个 ${},定义多个参数使用。
使用${} 定义参数时,{ }内写入的内容即为定义参数的内容,其中可以使用 FineReport 所有内置的函数,如 if 函数、len 函数等。{ }中除了 FineReport 内置的函数名、常量、字符串拼接语法外,其他变量就是数据集参数。
如:SELECT * FROM 销量 where 地区 = ‘${area}’ 中定义的数据集参数为 area。
带有数据集参数的 SQL 语句写好后,点击数据集定义界面「预览」按钮时,若显示出定义的数据集参数。则表明数据集参数定义成功。如下图所示:
在参数位置输入值后点击确定,参数值就会代入 SQL 语句中,查询出数据。
如下给出几种常见的应用方式,用户在使用时按实际场景调整即可。注意,因为数据集参数用在 SQL 查询语句中,所以在使用时,特别要注意语法和对应数据库类型的 SQL 语法匹配。
简单应用
如要定义一个地区参数,通过此参数过滤数据。新建数据集时,就可以在 SQL 查询语句中定义一个数据集参数 area:SELECT * FROM 销量 where 地区 = ‘${area}’
SQL 语句中,其他内容都是确定的,唯有 area 不确定,当 area 对应不同值时,数据集也将查询出不同地区的数据。
如果要实现多选查询,就可以结合 SQL 语句 in 的用法定义一个参数,如:SELECT * FROM 销量 where 地区 in (‘${area}’)
输入参数值时注意要和数据库语法一致,如查询华东华北的数据 SQL 语法为 SELECT * FROM 销量 where 地区 in (‘华东’,‘华北’),输入的参数值形式应该为 华东’,‘华北,这样加上定义时的 (’${area}') 就会拼接成正确的语法 ‘华东’,‘华北’。
带公式的应用
定义数据集参数时,可以使用 FineReport 所有内置函数。如需要定义一个地区参数,当地区为空时,查询所有地区的数据;当地区值不为空时,查询对应地区的数据:
SELECT * FROM 销量 where 1=1 ${if(len(area) == 0,“”,“and 地区 = '” + area + “'”)}
定义时,先使用函数 len 获取参数的长度,然后使用 if 函数进行判断
-
如果 area 参数的长度为 0,则内容为空,SQL 拼接后为 SELECT * FROM 销量 where 1=1;
-
如果 area 参数的长度不为 0,则将字符串 and 地区 = '、参数area、'拼接成一句 SQL ,如area的值为华东,那么参数定义部分的执行结果为and 地区=‘华东’,完整的 SQL 语句就变成:SELECT * FROM 销量 where 1=1 and 地区=‘华东’
定义多个参数
如果在数据过滤中,需要多个过滤条件,则可以定义多个数据集参数,如:
SELECT * FROM 销量 where 1=1 ${if(len(area) == 0,“”," and 地区 = ‘" + area + "’“)} ${if(len(product) == 0,”",“and 产品 = '” + product + “'”)}
其中使用了两次 ${},定义了两个数据集参数 area 和 province
嵌套应用
定义数据集参数时,也可以通过一些逻辑判断嵌套定义多个数据集参数。如:
SELECT * FROM 销量 where 1=1 ${if(len(area)!=0," and 地区=‘“+area+”’“,if(len(product)=0,”“,” and 产品=‘“+product+”’"))}
if 函数是 FineReport 内置的公式,变量 area 和 product 是数据集参数,如果len(area)!=0,即 area 参数不为空,即以
SELECT * FROM 销量 where 1=1 and 地区='area’查询,如地区为空,则要判断 len(product),若product参数为空,则不拼接任何查询条件,即查出所有,否则以 SELECT * FROM 销量 where 1=1 and 产品=‘product’ 查询。
示例
定义数据集参数
新建数据集 ds1,数据库查询对话框中写入 SQL 查询语句 SELECT * FROM 销量 WHERE 地区=‘${area}’,相当于在数据库查询语句中定义一个数据集参数area。点击右下角「刷新」按钮,下方数据集参数管理面板会显示已经新建好的数据集参数area,设置它的默认值为华东。点击「确定」,即同时完成了数据准备和定义数据集参数的工作。如下图所示:
表格样式设计
如下图所示设置表格样式,其中给表格选择预定义样式 Head类型的样式,标题字体自动居中。如下图所示:
将数据集中的字段拖入到对应单元格中,字体居中,给表格整体添加预定义样式默认的天蓝色内外框。如下图所示:
选中 C2 单元格,右边属性面板选择「单元格元素>基本」。数据设置下拉框选择汇总>求和。如下图所示:
参数添加控件
点击参数面板的「编辑」按钮,进入参数面板设置界面。如下图所示:
右上角控件设置面板会显示没有添加控件的参数,点击「area」或者点击「全部添加」,将参数的默认控件添加到参数面板。如下图所示:
注意:参数与控件是通过参数名称进行绑定的,也就是说当控件名称与参数名称一致时,参数与控件就进行了绑定,即在 Web 端给控件赋值就相当于给参数赋值。
参数area的默认控件添加到参数面板后,效果如下图所示:
注意:如果不想点击「全部添加」或「参数」快捷添加默认控件,也可以直接从控件栏中将控件拖拽到参数面板中,修改控件的名称与参数名称一致,即可将控件与参数进行绑定。
点击自定义控件的「编辑」按钮,选择下拉框控件类型,让用户通过下拉框选择参数值。如下图所示:
要想报表预览时点击「下拉框」可以出现参数值的选项,则需要设置下拉框的数据字典为销量表下的地区字段。
参数面板选中「下拉框控件」,右边属性面板选择「属性>数据字典」,点击数据字典「编辑」按钮,弹出数据字典设置对话框。数据字典的类型设置为数据库表,数据库为 FRDemo ,选择数据库表为销量,列名实际值和显示值都为地区。如下图所示:
注意:控件绑定数据字典时,当数据集中有和控件同名的参数时,不要使用,否则将造成循环引用,使得模板出错,如此处 ds1中有地区字段,和参数名同名 。
点击「标签控件」,将控件值命名为地区:。如下图所示:
将查询按钮往左边拖拽,形成紧凑式布局,让控件面板更加美观。再次点击参数面板的「编辑」按钮,完成参数控件的设置。如下图所示:
2.5.4.2 参数控件入门
2.5.4.2.1 控件与参数的绑定方式
在使用参数控件时,当已经完成全局参数、模板参数或数据集参数设置后,编辑参数面板,选择全部添加即可添加与参数绑定的参数控件,如下图所示:
编辑参数面板,选择需要的控件,设置参数控件的名称为对应的参数名也可以完成控件与参数绑定。例如:设置模板参数为货主地区,编辑参数面板,拖入下拉框控件,设置控件名称为货主地区。如下图所示:
2.5.4.2.2 文本控件
应用场景
参数面板处可以通过该控件输入文本信息,键入查询参数,如下图所示:
如何添加
将参数面板控件工具栏中的「文本控件」拖入到参数面板中,如下图所示:
属性设置
「文本控件」的属性设置界面如下图所示:
各属性设置项的详细介绍如下:
2.5.4.2.3 标签控件
应用场景
如何添加
将参数面板控件工具栏中的「标签控件」拖入到参数面板中,如下图所示:
属性设置
「标签控件」的属性设置界面如下图所示:
各属性设置项的详细介绍如下:
2.5.4.2.4 查询按钮控件
应用场景
「查询按钮」本质上也是一个按钮控件,但相比按钮控件,多了查询的功能。即「查询按钮」就是一个内置了查询功能的按钮控件。「查询按钮」只可应用在参数查询场景中,添加按钮后,点击按钮即可触发查询。如下图所示:
如何添加
一般定义了参数之后,参数面板默认会显示出添加的参数,点击即可添加一组参数查询控件,其中就包括了「查询按钮」。如下图所示:
除了以上自动添加的方式,用户还可以通过拖入的方式添加。如下图所示:
2.5.4.2.5 下拉框控件
应用场景
添加方式
将「下拉框控件」拖入到参数面板中,如下图所示:
属性设置
2.5.4.2.6 下拉复选框控件
应用场景
添加方式
将参数面板控件工具栏中的「下拉复选框控件」拖入到参数面板中,如下图所示:
属性设置
2.5.4.2.7 日期控件
应用场景
报表中添加日期查询控件,可以查询指定日期区间内的报表数据。如下图所示:
添加方式
将参数面板控件工具栏中的「日期控件」拖入到参数面板中,如下图所示:
属性设置
2.5.4.2.8 数字控件
应用场景
参数面板处可以通过该控件输入数字信息(整数、负数、小数),键入查询参数,如下图所示:
添加方式
属性设置
2.5.4.3 参数控件查询
2.5.4.3.1 下拉框筛选查询
预期效果
参数最主要的应用就是结合控件,实现数据筛选过滤。如下图所示:
实现思路
首先必须明确,参数和控件并非一个概念,但两者在绑定的情况下,就可以相互传值,参数值即为控件值,控件值即为参数值,所以就会产生参数和控件看起来是一样的错觉。
实现数据筛选过滤,即先将参数和控件绑定,控件选择值后传递给参数,报表根据参数值过滤出数据。参数和控件各司其职,控件负责选择值、参数负责过滤数据。
根据定义方法,参数可以分成数据集参数和模板参数,所以实现数据筛选查询,也对应两种方法,数据集参数方法和模板参数方法。
实现方法一: 数据集参数
定义数据集参数
通过数据集参数实现数据筛选过滤时,首先要定义一个数据集参数。如:SELECT * FROM 销量 where 地区 = ‘${area}’ 就定义了一个数据集参数 area。如下图所示:
添加过滤控件
定义好数据集参数后,如果要在页面实现数据过滤查询,就必须要有一个控件。根据想要的过滤形式选择控件即可,这里我们选择一个「下拉框」控件。
如下图所示,在参数面板添加了一个下拉框控件,并为为其绑定 数据字典,即设置「下拉框」的选项值为「销量」表的「地区」字段。如下图所示:
注意:添加控件后,一般需要添加一个「查询按钮」,直接从控件区域拖拽添加到参数面板即可。
绑定参数和控件
以上准备好了控件和参数,只要两者绑定即可实现数据过滤。参数和控件的绑定方式非常简单,名称一致即为绑定,这里参数值已经确定,所以只需要将控件名称改为参数值即可。如下图所示:
但一般情况下添加了参数后,参数面板默认会显示出添加的参数,方便用户将其与控件绑定。如下图所示:
点击参数即可将其添加在参数面板上,点击添加后默认添加一组过滤控件,分别为一个「标签控件」、一个「查询按钮」和一个未定义控件,用户根据需要给未定义控件选择类型即可。如下图所示:
自动添加后,控件名和参数名是一致的,即已经实现了绑定,就不需要再修改名称了。但控件还需要设置数据字典。
设计报表实现过滤
将数据集拖到报表中,设计报表,如下图所示:
保存模板,点击预览,area 控件选择不同的值,也就对应着 area 参数为不同的值,area 参数值不同,数据 SQL 语句就不同,则查询出的数据也就不同,这样就实现了数据过滤查询。如下图所示:
实现方法二: 模板参数
定义模板参数
定义一个模板参数 area。如下图所示:
添加过滤控件
定义好参数后,如果要在页面实现数据过滤查询,就必须要有一个控件。根据想要的过滤形式选择控件即可,这里我们选择一个「下拉框」控件。添加方法同方法一
绑定参数和控件
以上准备好了控件和参数,只要两者绑定即可实现数据过滤。参数和控件的绑定方式非常简单,名称一致即为绑定,这里参数值已经确定,所以只需要将控件名称改为参数值即可。绑定方法同方法一
添加过滤条件
新建数据集,SQL 语句为:SELECT * FROM 销量,即默认查询销量表中所有数据。将数据列添加到单元格中,并设置报表样式,如下图所示:
这时默认是所有数据,如果要实现查询,就必须添加过滤条件,双击 A2 单元格,为其添加过滤条件。过滤条件为地区这一列的值等于参数 area。如下图所示:
这样就实现了过滤,保存模板,点击预览,area 控件选择不同的值,也就对应着 area 参数为不同的值,area 参数值不同,报表中过滤条件就不同,则查询出的数据也就不同,这样就实现了数据过滤查询。如下图所示:
2.5.4.3.2 下拉复选框多值查询
预期效果
用户在实际使用时,可通过下拉复选框进行多选,效果如下图所示:
实现思路
使用下拉复选框控件,设置参数条件和过滤条件,从而实现多选应用场景。
实现方法一: 数据集参数
定义数据集参数
通过数据集参数实现数据筛选过滤时,首先要定义一个数据集参数。如:SELECT * FROM 车型销售数据 where 种类 in (‘${type}’); 就定义了一个数据集参数 type。如下图所示:
添加过滤控件
定义好数据集参数后,如果要在页面实现数据过滤查询,就必须要有一个控件。根据想要的过滤形式选择控件即可,这里我们选择一个「下拉复选框」控件。同时添加一个「查询按钮」。修改下拉复选框控件名称为type,和数据查询语句中的参数名一致,完成控件和参数绑定设置
绑定数据字典,新建数据库查询 ds2: SELECT distinct 种类 FROM 车型销售数据,查询下拉复选框中添加的种类数据,如下图所示:
数据字典中类型设置选择数据查询,数据集选择ds2,实际值和显示值选择种类列名
返回值类型选择字符串,分隔符修改为’,‘(即单引号中间加一个逗号,此处分隔符的设置是为了将所选的多个参数值分隔开,例:当地区选择 中型、微小型 时,返回值为 中型’,'微小型)
设计报表
设计报表样式,将对应的字段拖入单元格中,如下图所示:
效果预览
保存模板,点击「分页预览」。
实现方法二:模板参数
准备数据
新建普通报表,新增数据库查询 ds1:SELECT * FROM 车型销售数据,如下图所示:
设计报表
设计报表样式,将对应的字段拖入单元格中,如下图所示:
设置模板参数
设置下拉复选框控件
编辑参数面板,选择「全部添加」,选择「下拉复选框控件」,如下图所示:
点击「数据字典」,类型设置选择「数据查询」,数据集选择ds1,实际值和显示值均选择「种类」,如下图所示:
设置过滤条件
点击 A2 单元格,选择「过滤」,可选列选择种类,操作符为包含于,选择参数 $type,点击「增加」,如下图所示:
效果预览
保存模板,点击分页预览,效果如下图所示:
2.5.4.3.3 范围查询
预期效果
通过 控件筛选查询 ,可以实现单个参数、单个控件过滤数据,如果想要实现多个控件过滤数据,该怎么做呢?
如下图所示,想要查询一定时间范围内的数据:
实现思路
多个控件查询和单个控件查询思路基本一致,唯一的不同点为多个控件查询对应多个参数,所以多控件查询只需要在 控件筛选查询 的基础上稍作修改即可,也是通过数据集参数和模板参数两种方法实现。
数据集参数:在数据查询中定义数据集参数时,定义多个参数。
模板参数:定义多个模板参数,报表中添加多个过滤条件。
实现方法一:数据集参数
定义数据集参数
通过数据集参数实现数据筛选过滤,首先要定义数据集参数。如预期效果中我们要实现一个日期范围查询,需要开始时间和结束时间,则在定义数据集的时候就要分别定义开始时间和结束时间参数。定义如下:
SELECT * FROM 订单 where 1=1 and 订购日期>=‘ s t a r t t i m e ′ a n d 订购日期 < ′ {starttime}' and 订购日期<' starttime′and订购日期<′{endtime}’
这里定义了两个参数 starttime 和 endtime,分别对应开始时间和结束时间。如下图所示:
绑定过滤控件
如果要实现查询就必须绑定一个控件。点击参数面板,在参数面板「组件设置」处可以看到定义的 starttime 和 endtime 参数,点击将其添加在参数面板中,因为要查询时间,这里我们将其类型选择为「日期控件」。如下图所示:
将日期控件名称分别修改为starttime和endtime,然后根据实际情况修改控件属性中的控件值、格式、起始日期、和结束日期。以starttime日期控件为例:
设计报表实现过滤
将 ds1 数据集的数据列拖到报表中,设计报表样式,如下图所示:
保存模板,点击预览,在日期控件中选择开始日期和结束日期传递给 starttime 和 endtime 参数,则执行 SQL 语句查询出不同日期范围内的值。如下图所示:
实现方法二:模板参数
新建数据集,SQL 语句为:SELECT * FROM 订单,即默认查询订单表中所有数据。将数据列添加到单元格中,并设置报表样式,如下图所示:
创建模板参数
模板 -> 模板参数
添加过滤控件
同实现方法一步骤
添加过滤条件
双击 A2 单元格,为其添加过滤条件。过滤条件有两个
订购日期这一列的值大于或者等于参数 starttime
订购日期这一列的值小于参数 endtime
2.5.4.3.4 日期控件动态默认值查询
问题描述
日期控件想要根据当前时间来设置一个默认值,例如本月的月初和月末。
解决思路
利用日期类函数实现。
实现方法
报表设计
在参数面板放置 2 个日期控件,分别为开始日期和结束日期。
开始日期设置
选中开始日期控件,在「属性>高级>控件值」处选择公式,输入公式为:DATEINMONTH(TODAY(),1),表示当月的第一天,如图所示:
结束日期设置
选中结束日期控件,在「属性>高级>控件值」处选择公式,输入公式为:DATEINMONTH(TODAY(),-1),表示当月最后一天,如图所示:
如果要设置为日期格式,可以通过拼接字符串后转化格式的方式实现。如开始时间:today()+" 00:00:00"、结束时间:today()+" 23:59:59"
效果预览
2.5.4.3.5 参数为空查询全部
2.5.4.3.5.1 下拉框参数为空选择全部查询
问题描述
使用参数进行报表数据查询时,如果控件中参数值为空(控件中不输入参数值),点击查询后,不会显示任何报表数据。如下图所示:
我们需要实现的效果是,当控件中参数值为空,点击查询后,会显示报表中的全部数据。即在没有筛选条件的时候,显示报表所有内容,相当于不选值就不过滤。
解决思路
可通过使用模板参数和数据集参数实现报表查询,同时修改过滤条件和数据集定义方式来实现参数为空选择全部。
实现方法一: 模板参数
新建数据集
新建数据集ds1,输入数据库查询语句SELECT * FROM 订单,查询出订单表中的所有数据。如下图所示:
定义模板参数
定义一个模板参数「货主地区」,设置其默认值为「华北」。如下图所示:
编辑参数面板,点击「全部添加」,设置下拉框控件的数据字典为订单表中的数据列货主地区。如下图所示:
设计报表样式
设置过滤条件
给单元格 A2 添加数据过滤条件。双击 A2 单元格,在弹出的数据列对话框中选择过滤,添加一个普通条件,让数据列货主地区等于公式if(len( 货主地区 ) = = 0 , n o f i l t e r , 货主地区)==0,nofilter, 货主地区)==0,nofilter,货主地区),点击增加,点击确定,即通过添加过滤条件的方式实现参数为空选全部的效果。如下图所示:
注意:nofilter 表示不过滤,if(len( 货主地区 ) = = 0 , n o f i l t e r , 货主地区)==0,nofilter, 货主地区)==0,nofilter,货主地区) 表示参数「货主地区」为空,就不过滤数据,若不为空则以参数值进行过滤。
效果预览
保存报表,分页预览查看报表。如下图所示:
实现方法二: 数据集参数
新建数据集
在定义数据集参数时给它设置条件来实现参数为空选全部的效果,新建数据集 ds1,输入数据库查询语句:SELECT * FROM 订单 WHERE 1=1 ${if(len(area) == 0,“”,“and 货主地区 = '” + area + “'”)} ,此时数据集参数为「area」,设置参数默认值为华北,如下图所示:
公式中语句的注释如下:
where 1=1 表示条件永真,防止没有参数条件时,where 后面没有有效内容导致出错。
len(area)==0 表示参数「area」为空。
“and 货主地区='”+area+“'” 中间的「area」表示取参数值,‘+’ 为字符串拼接符号。
${if(len(area) == 0,“”,“and 货主地区 = '” +area + “'”)} 表示:
当参数「area」为空时,查询语句相当于:SELECT * FROM 订单
当参数「area」不为空时,查询语句相当于:SELECT * FROM 订单 WHERE 1=1 and 货主地区=‘${area}’
设计报表样式
添加参数控件
编辑参数面板,点击「全部添加」,设置下拉框控件的数据字典为订单表中的数据列货主地区。如下图所示:
修改标签控件的显示值为货主地区:。如下图所示:
效果预览
保存报表,分页预览查看报表。如下图所示:
2.5.4.3.5.2 下拉复选框参数为空选择全部查询
问题描述
在使用参数进行过滤时,选择某个参数值后就会根据选择的值进行过滤,但是如何实现如下图效果即货主地区下拉复选框中不选择参数值时能够查询出数据表中的全部值呢?效果如下图所示:
解决思路
下拉复选框可以通过报表参数或数据参数来实现复选,若需要实现参数为空选择全部,可取消勾选「点击查询前不显示报表内容」即可。
实现方法一: 模板参数
新建数据集
添加数据集 ds1,SQL 语句为:SELECT * FROM 订单。
报表设计
在第一行添加表头,将数据集ds1的字段依次拖入单元格中,如下图所示:
添加参数控件
添加一个标签控件,控件值设置为货主地区,如下图所示:
添加一个「下拉复选框控件」,控件名为 area ,数据字典选择数据库表,数据库为 FRDemo ,数据表为订单,实际值与显示值的列名都选择货主地区,返回值类型为数组,如下图所示:
添加查询控件,如下图所示:
点击参数面板空白处,在右侧的属性中,设置不勾选点击查询前不显示报表内容,如下图所示:
设置过滤条件
双击 A2 单元格,选择过滤按钮,给 A2 单元格增加过滤条件,可选列为货主地区,操作符为包含于,公式:if(len( a r e a ) = = 0 , n o f i l t e r , area)==0,nofilter, area)==0,nofilter,area) ,如下图所示:
实现方法二: 数据集参数
新建数据集
新建数据集ds1的 SQL 语句修改为:SELECT * FROM 订单 where 1=1 ${if(len(area) == 0,“”,“and 货主地区 in ('” + area + “')”)},
公式中 ${if(len(area) == 0,“”,“and 货主地区 in ('” + area + “')”)} 表示若参数 area 为空就不进行过滤,若不为空则货主地区等于参数值。如下图所示:
注意:where 1=1 表示条件永真,防止没有之后的参数条件时,where 多出而导致出错;len(area)==0 表示参数 area 为空;“and 货主地区='”+area+“'” 中间的 area 表示取参数值,‘+’ 为字符串拼接符号。
报表设计
添加参数控件
编辑参数面板,选择「全部添加」,将「标签控件」的控件值修改为货主地区:,「下拉复选框控件」的数据字典选择数据库表,数据库为 FRDemo ,数据表为订单,实际值与显示值的列名都选择货主地区,返回值类型为字符串,分隔符为 ‘,’ ,如下图所示:
2.6 数据决策系统
2.6.1 决策系统简介
2.6.1.1 概述
数据决策系统是 FineReport 自带的报表管理系统。
管理人员使用决策系统管理报表,包含权限分配、用户配置、系统管理等功能。普通用户登录决策系统查看自己权限内的报表。
2.6.1.2 决策系统初始化配置
注意:只有第一次打开决策系统时,需要对决策系统进行初始化配置。以后再打开决策系统,直接进入决策系统登录页面。
进入报表平台管理
FineReport 设计器安装之后,会默认打开平台初始化配置网页,如下图所示:
若初始化配置网页没有默认打开,可以点击 FineReport 设计器菜单栏「服务器>报表平台管理」打开。如下图所示:
设置管理员账号
在初始化配置页面中设置管理员账号的用户名和密码,点击「确定」,点击「下一步」按钮。如下图所示:
选择和配置数据库
进入数据库配置页面后,根据需要选择「内置数据库」或「外接数据库」。如下图所示:
内置数据库适用于个人本地试用,点击「直接登录」,可直接登录系统使用。
外接数据库适用于企业正式使用,点击「配置数据库」,为工程配置外接数据库。
登录决策系统
配置好数据库后,在登录页面输入设置好的管理员账号和密码,点击「登录」。如下图所示:
注:平台初始化配置后,可以通过点击 FineReport 设计器菜单栏「服务器>报表平台管理」的方式打开登录界面。
决策平台界面
目录界面:
管理系统界面:
2.6.2 管理系统
2.6.2.1 目录管理
应用场景
用户可在目录管理中,对平台和移动端目录进行增加、修改和删除等操作。
目录数量较多时,用户可在目录管理中进行搜索,快速找到指定目录。
功能简介
目录管理是对系统的虚拟目录进行设置,可对目录进行增加、修改和删除等操作。
管理员可进行目录的增删改查操作,可添加模板、链接、上报标签、目录等,本文将详细介绍。如下图所示:
添加目录
管理员进入数据决策系统,点击管理系统>目录管理>管理目录,选择添加目录,弹出如下对话框,输入文件夹名字,可对添加的文件夹进行描述等。
添加目录时,可选择该目录文件夹下面节点的展现终端,即该目录下面的所有模板可以在什么设备上查看,包括 PC、平板和手机。如下图所示:
点击确定,在左侧目录管理面板的「管理目录」下面成功新建了一个目录,如下图所示:
编辑目录
选中目录 FRtest ,右侧可以直接修改该目录的名称、描述、展示终端等设置,点击保存即可。如下图所示:
删除目录
选中目录 FRtest,点击目录后面的删除按钮,弹出提示:目录下的内容将与目录一起删除,是否确认删除?点击确定即可。如下图所示:
点击「目录列表」后面的符号,点击批量删除,则在每个文件前面出现单选框,可勾选要删除的目录。如下图所示:
添加模板
管理员可以在目录或子目录下添加模板,支持批量添加模板,支持分页报表、决策报表,支持填报模板,支持以数据分析方式查看模板;模板可以带参数并且可对参数设置默认值。
选中 FRtest 目录,在节点管理面板右侧点击添加模板按钮,弹出选择路径页面,在此可搜索、选择路径,支持多选,如下图所示:
点击下一步,在每个模板的配置项组上方都有对应的标题栏,点击标题栏可关闭或打开模板。
鼠标悬停在标题栏时,点击标题栏右侧的删除按钮可删除模板,如下图所示:
在模板设置界面,用户可修改路径、设置名称和描述等配置项,报表查看方式默认选择预览。点击设置默认参数值,在下方自动获取模板里面的参数并显示出来,示例如下图所示:
点击确定,在目录 FRtest 下新增了模板。选中模板,可删除模板,可在右侧直接修改模板属性值。
点击预览模板,可在新窗口中预览模板,如下图所示
打开目录,左侧目录树中显示刚刚添加的模板,如下图所示:
2.6.2.2 用户管理
手动添加用户
管理员登录数据决策系统,点击「管理系统>用户管理>所有用户」,点击「添加用户」,可设置用户信息并添加,点击「确定」,添加成功。如下图所示:
编辑用户
管理员
对于手动添加的用户,支持管理员编辑其基本信息和角色,编辑完成后点击「确定」,修改成功,如下图所示:
用户
对于手动添加的用户,用户登录数据决策系统后,点击「右上角头像」,点击「账号设置」,可修改用户姓名、手机、邮箱、密码,如下图所示:
禁用用户
手动添加的用户默认为启用状态。
管理员点击「禁用用户」按钮,「确定」禁用,即可禁用用户,如下图所示:
删除用户
手动添加的用户,支持批量删除或单个删除。如下图所示:
2.6.2.3 权限管理
系统管理权限
开启分级权限
管理员登录数据决策系统,点击「管理系统>权限管理>全局设置」,开启「分级授权」按钮,点击「保存」。如下图所示:
注意:如需分配「管理系统」权限,则必须开启「分级授权」按钮。
配置管理系统使用权限
管理员登录数据决策系统,点击「管理系统>权限管理>普通权限配置」,选择权限载体「部门/角色/用户」,本示例选择用户 eoco。
选择「管理系统」Tab,为 eoco 配置模块「系统管理」和「智能运维」的「使用」权限,如下图所示:
效果预览
用户 eoco 登录数据决策系统,点击「管理系统」,可进行「系统管理」和「智能运维」的使用操作。如下图所示:
人员管理权限
开启分级权限
管理员登录数据决策系统,点击「管理系统>权限管理>全局设置」,开启「分级授权」按钮,点击「保存」。如下图所示:
注意:如需分配「管理系统」权限,则必须开启「分级授权」按钮。
配置人员管理权限
管理员登录数据决策系统,点击「管理系统>权限管理>授权权限配置」,选择权限载体「部门/角色/用户」,本示例选择用户 eoco。
选择「人员管理」Tab,为 eoco 配置部门「人力资源」和角色「普通角色1」的「授权」权限,如下图所示:
配置管理系统授权权限
管理员登录数据决策系统,点击「管理系统>权限管理>授权权限配置」,选择权限载体「部门/角色/用户」,本示例选择用户 eoco。
选择「管理系统」Tab,为 eoco 配置模块「用户管理」的「授权」权限,如下图所示:
配置管理系统使用权限
管理员登录数据决策系统,点击「管理系统>权限管理>普通权限配置」,选择权限载体「部门/角色/用户」,本示例选择用户 eoco。
选择「管理系统」Tab,为 eoco 配置模块「权限管理」的「使用」权限,如下图所示:
效果查看
用户 eoco 登录数据决策系统,点击「管理系统>权限管理」,可以给有权限的部门/角色授予「人员管理」的管理权限。如下图所示:
目录权限
查看权限
管理员登录数据决策系统,点击「管理系统>权限管理>普通权限配置」,切换当前查看维度为「用户组维度」。
选择权限载体「部门/角色/用户」,本示例选择用户eoco,为其分配目录「管理驾驶舱」的「查看」权限,如下图所示:
用户「eoco」可以查看目录「管理驾驶舱」和下级目录下挂载的模板,如下图所示:
授权权限
开启分级权限
管理员登录数据决策系统,点击「管理系统>权限管理>全局设置」,开启「分级授权」按钮,点击「保存」。如下图所示:
注意:如需分配「授权」权限,则必须开启「分级授权」按钮。
配置目录授权权限
管理员登录数据决策系统,点击「管理系统>权限管理>授权权限配置」,选择权限载体「部门/角色/用户」,本示例选择用户 eoco。
选择「目录权限」Tab,为 eoco 配置目录「管理驾驶舱」的「授权」权限,如下图所示:
配置人员管理授权权限
管理员登录数据决策系统,点击「管理系统>权限管理>授权权限配置」,选择权限载体「部门/角色/用户」,本示例选择用户 eoco。
选择「人员管理」Tab,为 eoco 配置部门「人力资源」的「授权」权限,如下图所示:
配置管理系统使用权限
管理员登录数据决策系统,点击「管理系统>权限管理>普通权限配置」,选择权限载体「部门/角色/用户」,本示例选择用户 eoco。
选择「管理系统」Tab,为 eoco 配置模块「权限管理」的「使用」权限,如下图所示:
效果查看
用户 eoco 登录数据决策系统,点击「管理系统>权限管理>普通权限配置」,可给部门「人力资源」配置目录「管理驾驶舱」的查看权限。如下图所示:
- 数据报表综合案例
数据报表工作流程
需求分析,确定数据都在哪些表中获取
计算数据指标,并保存到数据库
脚本定时,按指定日期进行数据更新
通过FineReport给业务人员展示报表
3.1 统计各省份门店店铺注册数量
3.1.1 需求分析
业务方需要查看各省份的已认证门店店铺注册数量,需要查看的字段有省份、门店注册数量、店铺注册数量以及统计日期。门店注册数量和店铺注册数量分别在门店表和店铺表中,而省份名称是在地区表中保存。我们需要分别计算已认证门店注册数量和已认证店铺注册数量,然后和地区表关联获取省份名称。要求统计不包含港澳台海外测试门店店铺的数据,数据每天进行更新。
在门店表中分组计算各省份门店注册数量,获取areaid_1(省份id)和门店注册数量(不包含测试门店)
在店铺表中分组计算各省份店铺注册数量,获取areaid_1(省份id)和店铺注册数量(不包含测试店铺)
统计日期
统计周期以天为单位进行统计,每天24点统计历史数据,可以支持按天筛选。
3.1.2 需求数据指标计算
门店表 uc_chain
字段名称 字段解释 字段说明
chain_id 门店id
member_id 买家id 等同于订单表中buyer_id字段
chain_user App账号登录名
chain_name 门店名称
areaid_1 省份id 地区表中关联字段
areaid_2 市id 地区表中关联字段
areaid_3 县id 地区表中关联字段
chain_status 门店状态:1.正常 2.关闭
is_auth 是否认证:0未认证 1已认证
audit_status 审核状态:0:默认待更新资料 1:待审核(中) 2:已审核 3:已拒绝
add_time 门店添加时间 门店注册时间
update_time 门店修改时间
店铺表 uc_store
字段名称 字段解释 字段说明
store_id 店铺id
store_name 店铺名称
member_id 买家id 等同于订单表中buyer_id字段
member_name 会员名称
areaid_1 省份id 地区表中关联字段
areaid_2 市id 地区表中关联字段
areaid_3 县id 地区表中关联字段
store_state 店铺状态,0关闭,1开启,2审核中
is_auth 是否认证:0未认证 1已认证 2认证审核中
add_time 店铺添加时间 店铺注册时间
update_time 店铺修改时间
地区表 shopnc_area
字段名称 字段解释
area_id 地区id 省市县id
area_name 地区名称(省、市、县)
计算各省份认证门店注册数量(不包含测试数据)
– 获取areaid_1字段,为了和地区表关联获取省份名称
– 门店表中一条数据为一家门店数据,计算各省份门店注册数量,即对一级地区id字段进行分组,门店id字段进行count()操作,避免数据表中存在重复数据,进行去重操作
– 限制条件,计算已认证注册门店数,排除测试门店,统计当天之前的数据
– 注册时间为时间戳格式,CURDATE()获取当天日期,如:‘2021-09-17’,UNIX_TIMESTAMP()将日期格式转换为时间戳格式
SELECT
areaid_1,
COUNT(DISTINCT chain_id) AS chain_num
FROM
uc_chain
WHERE
is_auth = 1
AND chain_name NOT LIKE ‘%test%’
AND chain_name NOT LIKE ‘%测试%’
AND add_time < UNIX_TIMESTAMP(CURDATE())
GROUP BY
areaid_1;
SELECT CURDATE();
– 2021-09-17 日期格式
SELECT UNIX_TIMESTAMP(CURDATE());
– 1631836800 时间戳格式
计算各省份认证店铺注册数量(不包含测试数据)
– 获取areaid_1字段,为了和地区表关联获取省份名称
– 店铺表中一条数据为一家门店数据,计算各省份店铺注册数量,即对一级地区id字段进行分组,店铺id字段进行count()操作,避免数据表中存在重复数据,进行去重操作
– 限制条件,计算已认证注册店铺数,排除测试店铺,统计当天之前的数据
SELECT
areaid_1,
COUNT(DISTINCT store_id) AS store_num
FROM
uc_store
WHERE
add_time < UNIX_TIMESTAMP(CURDATE())
and is_auth = 1
and store_name not like ‘%test%’
and store_name not like ‘%测试%’
GROUP BY areaid_1;
获取省份名称,排除港澳台海外四个地区
– 地区表中,省市县三个地区id都存放到了一起,地区id唯一,排除港澳台海外地区,即地区id字段小于32
SELECT
area_id,
area_name AS province
FROM
shopnc_area
WHERE
area_id < 32;
三个sql查询语句进行关联查询
SELECT
area.province, – 省份
chains.chain_num all_chain, – 门店数
store.store_num all_store, – 店铺数
CURDATE() collect_time – 统计时间
FROM – 省份信息
(SELECT
area_id,
area_name AS province
FROM
shopnc_area
WHERE
area_id < 32) area
LEFT JOIN – 注册门店数
(SELECT
areaid_1,
COUNT(DISTINCT chain_id) AS chain_num
FROM
uc_chain
WHERE
is_auth = 1
AND chain_name NOT LIKE ‘%test%’
AND chain_name NOT LIKE ‘%测试%’
AND add_time < UNIX_TIMESTAMP(CURDATE())
GROUP BY
areaid_1) chains ON chains.areaid_1 = area.area_id
LEFT JOIN – 注册店铺数
(SELECT
areaid_1,
COUNT(DISTINCT store_id) AS store_num
FROM
uc_store
WHERE
add_time < UNIX_TIMESTAMP(CURDATE())
AND is_auth = 1
AND store_name NOT LIKE ‘%test%’
AND store_name NOT LIKE ‘%测试%’
GROUP BY
areaid_1) store ON store.areaid_1 = area.area_id;
报表数据保存到mysql数据库
创建 daily_all_store_chain 表
CREATE TABLE IF NOT EXISTS daily_all_store_chain
(
province VARCHAR(20) COMMENT ‘省份’,
all_chain INT COMMENT ‘注册门店数’,
all_store INT COMMENT ‘注册店铺数’,
collect_time DATE COMMENT ‘统计时间’
);
向表中插入数据
INSERT INTO
daily_all_store_chain
SELECT
area.province, – 省份
chains.chain_num all_chain, – 门店数
store.store_num all_store, – 店铺数
CURDATE() collect_time – 统计时间
FROM – 省份信息
(SELECT
area_id,
area_name AS province
FROM
shopnc_area
WHERE
area_id < 32) area
LEFT JOIN – 注册门店数
(SELECT
areaid_1,
COUNT(DISTINCT chain_id) AS chain_num
FROM
uc_chain
WHERE
is_auth = 1
AND chain_name NOT LIKE ‘%test%’
AND chain_name NOT LIKE ‘%测试%’
AND add_time < UNIX_TIMESTAMP(CURDATE())
GROUP BY
areaid_1) chains ON chains.areaid_1 = area.area_id
LEFT JOIN – 注册店铺数
(SELECT
areaid_1,
COUNT(DISTINCT store_id) AS store_num
FROM
uc_store
WHERE
add_time < UNIX_TIMESTAMP(CURDATE())
AND is_auth = 1
AND store_name NOT LIKE ‘%test%’
AND store_name NOT LIKE ‘%测试%’
GROUP BY
areaid_1) store ON store.areaid_1 = area.area_id;
3.1.3 编写python脚本
编写python脚本代码 daily_all_store_chain.py
import pandas as pd
from sqlalchemy import create_engine
import warnings
忽略警告
warnings.filterwarnings(‘ignore’)
“”"
安装第三方模块
pip install pymsql -i https://pypi.tuna.tsinghua.edu.cn/simple/
pip install sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple/
pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple/
“”"
创建mysql数据库链接
root:账号
123456:密码
192.168.88.100:ip地址
3306:端口号
shopnc_db:数据库名称
生产库链接
shopnc_engine = create_engine(‘mysql+pymysql://root:123456@192.168.88.100:3306/shopnc_db’)
BI库链接
bi_engine = create_engine(‘mysql+pymysql://root:123456@192.168.88.100:3306/BI_db’)
sql语句
daily_all_store_chain_sql = “”"
SELECT
area.province, – 省份
chains.chain_num all_chain, – 门店数
store.store_num all_store, – 店铺数
CURDATE() collect_time – 统计时间
FROM – 省份信息
(SELECT
area_id,
area_name AS province
FROM
shopnc_area
WHERE
area_id < 32) area
LEFT JOIN – 注册门店数
(SELECT
areaid_1,
COUNT(DISTINCT chain_id) AS chain_num
FROM
uc_chain
WHERE
is_auth = 1
AND chain_name NOT LIKE ‘%%test%%’
AND chain_name NOT LIKE ‘%%测试%%’
AND add_time < UNIX_TIMESTAMP(CURDATE())
GROUP BY
areaid_1) chains ON chains.areaid_1 = area.area_id
LEFT JOIN – 注册店铺数
(SELECT
areaid_1,
COUNT(DISTINCT store_id) AS store_num
FROM
uc_store
WHERE
add_time < UNIX_TIMESTAMP(CURDATE())
AND is_auth = 1
AND store_name NOT LIKE ‘%%test%%’
AND store_name NOT LIKE ‘%%测试%%’
GROUP BY
areaid_1) store ON store.areaid_1 = area.area_id
“”"
读取mysql数据库中的数据
daily_all_store_chain_data = pd.read_sql(daily_all_store_chain_sql, con=shopnc_engine)
将读取的数据保存到mysql数据库中
name: 表名
con: 数据库链接
if_exists: 数据保存方式 replace->覆盖保存 append:追加保存
index: 是否保留索引序号列, True保留, False保留
daily_all_store_chain_data.to_sql(name=“daily_all_store_chain”, con=bi_engine, if_exists=“append”, index=False)
将 daily_all_store_chain.py上传到服务器,需要在py文件开头添加 # -- coding: UTF-8 --,指定编码格式,防止出现中文乱码问题
-- coding: UTF-8 --
import pandas as pd
from sqlalchemy import create_engine
import warnings
忽略警告
warnings.filterwarnings(‘ignore’)
创建mysql数据库链接
root:账号
123456:密码
192.168.88.100:ip地址
3306:端口号
shopnc_db:数据库名称
生产库链接
shopnc_engine = create_engine(‘mysql+pymysql://root:123456@192.168.88.100:3306/shopnc_db’)
BI库链接
bi_engine = create_engine(‘mysql+pymysql://root:123456@192.168.88.100:3306/BI_db’)
sql语句
daily_all_store_chain_sql = “”"
SELECT
area.province, – 省份
chains.chain_num all_chain, – 门店数
store.store_num all_store, – 店铺数
CURDATE() collect_time – 统计时间
FROM – 省份信息
(SELECT
area_id,
area_name AS province
FROM
shopnc_area
WHERE
area_id < 32) area
LEFT JOIN – 注册门店数
(SELECT
areaid_1,
COUNT(DISTINCT chain_id) AS chain_num
FROM
uc_chain
WHERE
is_auth = 1
AND chain_name NOT LIKE ‘%%test%%’
AND chain_name NOT LIKE ‘%%测试%%’
AND add_time < UNIX_TIMESTAMP(CURDATE())
GROUP BY
areaid_1) chains ON chains.areaid_1 = area.area_id
LEFT JOIN – 注册店铺数
(SELECT
areaid_1,
COUNT(DISTINCT store_id) AS store_num
FROM
uc_store
WHERE
add_time < UNIX_TIMESTAMP(CURDATE())
AND is_auth = 1
AND store_name NOT LIKE ‘%%test%%’
AND store_name NOT LIKE ‘%%测试%%’
GROUP BY
areaid_1) store ON store.areaid_1 = area.area_id
“”"
读取mysql数据库中的数据
daily_all_store_chain_data = pd.read_sql(daily_all_store_chain_sql, con=shopnc_engine)
将读取的数据保存到mysql数据库中
name: 表名
con: 数据库链接
if_exists: 数据保存方式 replace->覆盖保存 append:追加保存
index: 是否保留索引序号列, True保留, False保留
daily_all_store_chain_data.to_sql(name=“daily_all_store_chain”, con=bi_engine, if_exists=“append”, index=False)
3.1.4 定时调度脚本
编写 finereport_project.sh shell脚本,执行python文件
/export/server/anaconda3/bin/python3 /root/finereport_file/daily_all_store_chain.py &>> /root/finereport_file/log.txt
修改 sh脚本权限, 改成可执行
chmod 777 finereport_project.sh
使用linux服务器的crontab模块进行定时调度
crontab -e # 输入linux命令,编辑定时调用文件
将以下内容添加到文件中, 每天凌晨12点执行任务,跑数据
0 0 * * * /root/finereport_file/finereport_project.sh
crontab相关命令:
(1)语 法:
crontab [-u <用户名称>][配置文件] 或 crontab { -l | -r | -e }
-u #<用户名称> 是指设定指定<用户名称>的定时任务,这个前提是你必须要有其权限(比如说是 root)才能够指定他人的时程表。如果不使用 -u user 的话,就是表示设定自己的定时任务。
-l #列出该用户的定时任务设置。
-r #删除该用户的定时任务设置。
-e #编辑该用户的定时任务设置。
(2)命令时间格式 :
-
* * * * command
分 时 日 月 周 命令
第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令
(3)一些Crontab定时任务例子:
30 21 * * * /usr/local/etc/rc.d/lighttpd restart #每晚的21:30 重启apache
45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart #每月1、10、22日的4 : 45重启apache
10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart #每周六、周日的1 : 10重启apache
0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart #每天18 : 00至23 : 00之间每隔30分钟重启apache
0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart #每星期六的11 : 00 pm重启apache
- 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart #晚上11点到早上7点之间,每隔一小时重启apache
- */1 * * * /usr/local/etc/rc.d/lighttpd restart #每一小时重启apache
0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart #每月的4号与每周一到周三的11点重启apache
0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart #一月一号的4点重启apache
/30 * * * * /usr/sbin/ntpdate cn.pool.ntp.org #每半小时同步一下时间
0 /2 * * * /sbin/service httpd restart #每两个小时重启一次apache
50 7 * * * /sbin/service sshd start #每天7:50开启ssh服务
50 22 * * * /sbin/service sshd stop #每天22:50关闭ssh服务
0 0 1,15 * * fsck /home #每月1号和15号检查/home 磁盘
1 * * * * /home/bruce/backup #每小时的第一分执行 /home/bruce/backup这个文件
00 03 * * 1-5 find /home ".xxx" -mtime +4 -exec rm {} ; #每周一至周五3点钟,在目录/home中,查找文件名为.xxx的文件,并删除4天前的文件。
30 6 */10 * * ls #每月的1、11、21、31日是的6:30执行一次ls命令
3.1.5 制作需求报表
3.1.5.1 报表要求
报表展示 地区,累计入驻门店数,累计入驻店铺数 以及 统计时间 信息
默认显示当前日期的数据信息
可以实现筛选任意日期的数据信息
筛选日期为空时显示全部数据信息
3.1.5.2 制作流程
新建数据集ds1,查询语句为 SELECT * FROMdaily_all_chain_storewhere 1=1 ${if(len(day) == 0,“”,“and collect_time = '” + day + “'”)};,参数day默认值修改为公式 =TODAY()。
设计报表样式
依次将ds1中的字段拖拽到单元格A3~D3位置,添加如下报表标题和表头
合并第一行单元格,添加 xxx公司各地区招商累计报表 标题
将第一行和第二行单元格属性中样式修改为预定义样式
将第一行和第二行设置重复与冻结
添加参数控件
添加文本控件,下拉框控件,查询按钮
将文本控件值修改为 统计日期:
将下拉框控件的控件名称修改为 day,与命名参数同名,参数和控件自动绑定
下拉框控件添加数据字典
创建数据库查询ds2,查询语句:SELECT collect_time FROMdaily_all_chain_storegroup by collect_time 查询统计日期数据
数据字典绑定ds2中的collect_time列名,类型设置选择数据查询,数据集选择ds2,实际值和显示值选择collect_time列。
报表预览
点击保存报表,然后分页预览。
报表效果
取消勾选para控件中的点击查询前不显示报表内容,分页预览时会自动显示报表内容。
3.1.5.3 报表部署
管理员身份登录数据决策系统,选择服务器,点击报表平台管理
点击管理系统->目录管理->添加模板,添加制作好的报表,点击下一步,然后点击确定
给用户设置查看此报表的权限
3.2 统计各省份批发订单业务进展情况
3.2.1 需求分析
运营人员需要查看公司当月(2020-10)以及上月同期(2020-09)各省份批发订单业务进展如何,需要查看的数据指标如下:
当月订单数:对shopnc_pf_orders 表中order_id进行计数计算
上月同期订单数: 同当月订单数计算逻辑
当月订单金额: 对shopnc_pf_orders 表中order_amount字段进行求和计算
上月同期订单金额: 同当月订单金额计算逻辑
当月下单门店数: 对shopnc_pf_orders 表中buyer_id进行去重计数计算
上月同期下单门店数: 同当月下单门店数计算逻辑
当月门店激活数: 当月门店总订单金额大于等于1000的即为激活门店
当月门店激活率: 当月门店激活数除以总门店数
当月店铺激活数: 当月店铺总订单金额大于等于5000的即为激活店铺
当月店铺激活率: 当月激活店铺数除以总店铺数
以上统计时间以订单支付时间为准,将批发订单业务指标保存到数据库中,指标数据每天进行更新,通过报表形式展现给运营人员。
3.2.2 需求指标计算
批发订单表 shopnc_pf_orders
字段名 字段解释 字段说明
order_id 订单id
store_id 卖家店铺id 同uc_store表中store_id
buyer_id 买家id 同uc_chain/uc_store表中member_id
add_time 订单生成时间 时间戳
payment_time 订单支付时间 统计订单数据以此时间为准
finnshed_time 订单完成时间
order_amount 订单金额
order_state 订单状态 0(已取消)10(默认):未付款;20:已付款;30:已发货;40:已收货;50:已拒付;60:已关闭(转单成功后关闭) 统计订单以20,30,40为准
order_type 订单类型 3批发订单 5大宗交易
统计当月(2020-10)批发订单指标数据
统计各门店批发订单数和批发订单总金额
SELECT
buyer_id, – 门店会员id
count(order_id) order_num, – 订单数
sum(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3 – 批发订单
AND order_state IN (20, 30, 40) – 支付订单
GROUP BY buyer_id;
统计当月(2020-10)各省份批发订单数、批发订单总金额、下单门店数和激活门店数
SELECT
chains.areaid_1, – 省份id
SUM(orders.order_num) pf_order_sum, – 订单数
SUM(orders.order_amount) pf_order_amount, – 订单总金额
COUNT(DISTINCT orders.buyer_id) pf_order_chain_sum, – 下单门店数
SUM(CASE WHEN orders.order_amount >= 1000 THEN 1 ELSE 0 END) active_chain – 激活门店数
FROM
(SELECT
buyer_id, – 门店会员id
COUNT(order_id) order_num, – 订单数
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3 – 批发订单
AND order_state IN (20, 30, 40) – 支付订单
GROUP BY buyer_id) orders
– 关联门店表,获取省份id
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
GROUP BY
chains.areaid_1;
统计上月(2020-09)同期批发订单指标数据
SELECT
chains.areaid_1, – 省份id
COUNT(DISTINCT orders.order_id) t_pf_order_sum, – 同期订单数
SUM(orders.order_amount) t_pf_order_amount, – 同期订单总金额
COUNT(DISTINCT orders.buyer_id) t_pf_order_chain_sum – 同期下单门店数
FROM
shopnc_pf_orders orders
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-09-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-10-01’
AND orders.order_type = 3
AND orders.order_state IN (20, 30, 40)
GROUP BY
chains.areaid_1;
统计各省门店数
– 门店激活率 = 门店激活数 / 总门店数,所以要先计算各省门店数
SELECT
areaid_1, – 省份id
COUNT(DISTINCT chain_id) chain_num – 门店数
FROM
uc_chain
WHERE
is_auth = 1 – 认证门店
AND from_unixtime(add_time) < ‘2020-11-01’
GROUP BY
areaid_1;
统计各省店铺数
– 店铺激活率 = 店铺激活数 / 总店铺数,所以要先计算各省店铺数
SELECT
areaid_1, – 省份id
COUNT(DISTINCT store_id) store_num – 店铺数
FROM
uc_store
WHERE
is_auth = 1
AND FROM_UNIXTIME(add_time) < ‘2020-11-01’
GROUP BY
areaid_1;
统计当月(2020-10)各省激活店铺数
统计当月各店铺的订单总金额
SELECT
store_id, – 店铺id
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
store_id;
各省激活店铺数
SELECT
store.areaid_1, – 省份id
SUM(CASE WHEN orders.order_amount >= 5000 THEN 1 ELSE 0 END) active_store – 激活店铺数
FROM
(SELECT
store_id, – 店铺id
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
store_id) orders
LEFT JOIN uc_store store ON store.store_id = orders.store_id
GROUP BY
store.areaid_1;
需求总sql
SELECT
area.area_name province, – 省份名称
IFNULL(dmonth.pf_order_sum, 0) pf_order_sum, – 当月订单数
IFNULL(tmonth.t_pf_order_sum, 0) t_pf_order_sum, – 上月同期订单数
IFNULL(dmonth.pf_order_amount, 0) pf_order_amount, – 当月订单总金额
IFNULL(tmonth.t_pf_order_amount, 0) t_pf_order_amount, – 上月同期订单总金额
IFNULL(dmonth.pf_order_chain_sum, 0) pf_order_chain_sum, – 当月下单门店数
IFNULL(tmonth.t_pf_order_chain_sum, 0) t_pf_order_chain_sum, – 上月同期下单门店数
IFNULL(dmonth.active_chain, 0) active_chain, – 门店激活数
IFNULL(dmonth.active_chain, 0) / chains.chain_num chain_active_ratio, – 门店激活率
IFNULL(active_s.active_store, 0) active_store, – 店铺激活数
IFNULL(active_s.active_store, 0) / stores.store_num store_active_ratio, – 店铺激活率
CURDATE() collect_time – 统计时间
FROM
shopnc_area area
LEFT JOIN – 当月批发订单数据
(SELECT
chains.areaid_1, – 省份id
SUM(orders.order_num) pf_order_sum, – 订单数
SUM(orders.order_amount) pf_order_amount, – 订单总金额
COUNT(DISTINCT orders.buyer_id) pf_order_chain_sum, – 下单门店数
SUM(CASE WHEN orders.order_amount >= 1000 THEN 1 ELSE 0 END) active_chain – 激活门店数
FROM
(SELECT
buyer_id, – 门店id
COUNT(order_id) order_num, – 订单数
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3 – 批发订单
AND order_state IN (20, 30, 40) – 支付订单
GROUP BY buyer_id) orders
– 关联门店表,获取省份id
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
GROUP BY
chains.areaid_1) dmonth ON area.area_id = dmonth.areaid_1
LEFT JOIN – 上月同期批发订单数据
(SELECT
chains.areaid_1, – 省份id
COUNT(DISTINCT orders.order_id) t_pf_order_sum, – 同期订单数
SUM(orders.order_amount) t_pf_order_amount, – 同期订单总金额
COUNT(DISTINCT orders.buyer_id) t_pf_order_chain_sum – 同期下单门店数
FROM
shopnc_pf_orders orders
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-09-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-10-01’
AND orders.order_type = 3
AND orders.order_state IN (20, 30, 40)
GROUP BY
chains.areaid_1) tmonth ON tmonth.areaid_1 = area.area_id
LEFT JOIN – 各省份门店总数
(SELECT
areaid_1, – 省份id
COUNT(DISTINCT chain_id) chain_num – 门店数
FROM
uc_chain
WHERE
is_auth = 1 – 认证门店
AND FROM_UNIXTIME(add_time) < ‘2020-11-01’
GROUP BY
areaid_1) chains ON chains.areaid_1 = area.area_id
LEFT JOIN – 各省份店铺总数
(SELECT
areaid_1, – 省份id
COUNT(DISTINCT store_id) store_num – 店铺数
FROM
uc_store
WHERE
is_auth = 1
AND FROM_UNIXTIME(add_time) < ‘2020-11-01’
GROUP BY
areaid_1) stores ON stores.areaid_1 = area.area_id
LEFT JOIN – 各省份激活店铺数
(SELECT
store.areaid_1, – 省份id
SUM(CASE WHEN orders.order_amount >= 5000 THEN 1 ELSE 0 END) active_store – 激活店铺数
FROM
(SELECT
store_id, – 店铺id
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
store_id) orders
LEFT JOIN uc_store store ON store.store_id = orders.store_id
GROUP BY
store.areaid_1) active_s ON active_s.areaid_1 = area.area_id
WHERE
area_id < 32; – 过滤港澳台
报表数据保存到mysql数据库
创建 daily_all_pf_orders 表
CREATE TABLE IF NOT EXISTS daily_all_pf_orders
(
province VARCHAR(20) COMMENT ‘省份’,
pf_order_sum INT COMMENT ‘当月订单数’,
t_pf_order_sum INT COMMENT ‘上月同期订单数’,
pf_order_amount DOUBLE COMMENT ‘当月订单总金额’,
t_pf_order_amount DOUBLE COMMENT ‘上月同期订单总金额’,
pf_order_chain_sum INT COMMENT ‘当月下单门店数’,
t_pf_order_chain_sum INT COMMENT ‘上月同期下单门店数’,
active_chain INT COMMENT ‘门店激活数’,
chain_active_ratio DOUBLE COMMENT ‘门店激活率’,
active_store INT COMMENT ‘店铺激活数’,
store_active_ratio DOUBLE COMMENT ‘店铺激活率’,
collect_time DATE COMMENT ‘统计时间’
);
向表中插入数据
INSERT INTO
daily_all_pf_orders
SELECT
area.area_name province, – 省份名称
IFNULL(dmonth.pf_order_sum, 0) pf_order_sum, – 当月订单数
IFNULL(tmonth.t_pf_order_sum, 0) t_pf_order_sum, – 上月同期订单数
IFNULL(dmonth.pf_order_amount, 0) pf_order_amount, – 当月订单总金额
IFNULL(tmonth.t_pf_order_amount, 0) t_pf_order_amount, – 上月同期订单总金额
IFNULL(dmonth.pf_order_chain_sum, 0) pf_order_chain_sum, – 当月下单门店数
IFNULL(tmonth.t_pf_order_chain_sum, 0) t_pf_order_chain_sum, – 上月同期下单门店数
IFNULL(dmonth.active_chain, 0) active_chain, – 门店激活数
IFNULL(dmonth.active_chain, 0) / chains.chain_num chain_active_ratio, – 门店激活率
IFNULL(active_s.active_store, 0) active_store, – 店铺激活数
IFNULL(active_s.active_store, 0) / store.store_num store_active_ratio, – 店铺激活率
CURDATE() collect_time – 统计时间
FROM
shopnc_area area
LEFT JOIN – 当月批发订单数据
(SELECT
chains.areaid_1, – 省份id
SUM(orders.order_num) pf_order_sum, – 订单数
SUM(orders.order_amount) pf_order_amount, – 订单总金额
COUNT(DISTINCT orders.buyer_id) pf_order_chain_sum, – 下单门店数
SUM(CASE WHEN orders.order_amount >= 1000 THEN 1 ELSE 0 END) active_chain – 激活门店数
FROM
(SELECT
buyer_id, – 门店会员id
COUNT(order_id) order_num, – 订单数
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3 – 批发订单
AND order_state IN (20, 30, 40) – 支付订单
GROUP BY buyer_id) orders
– 关联门店表,获取省份id
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
GROUP BY
chains.areaid_1) dmonth ON area.area_id = dmonth.areaid_1
LEFT JOIN – 上月同期批发订单数据
(SELECT
chains.areaid_1, – 省份id
COUNT(DISTINCT orders.order_id) t_pf_order_sum, – 同期订单数
SUM(orders.order_amount) t_pf_order_amount, – 同期订单总金额
COUNT(DISTINCT orders.buyer_id) t_pf_order_chain_sum – 同期下单门店数
FROM
shopnc_pf_orders orders
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-09-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-10-01’
AND orders.order_type = 3
AND orders.order_state IN (20, 30, 40)
GROUP BY
chains.areaid_1) tmonth ON tmonth.areaid_1 = area.area_id
LEFT JOIN – 各省份门店总数
(SELECT
areaid_1, – 省份id
COUNT(DISTINCT chain_id) chain_num – 门店数
FROM
uc_chain
WHERE
is_auth = 1 – 认证门店
AND FROM_UNIXTIME(add_time) < ‘2020-11-01’
GROUP BY
areaid_1) chains ON chains.areaid_1 = area.area_id
LEFT JOIN – 各省份店铺总数
(SELECT
areaid_1, – 省份id
COUNT(DISTINCT store_id) store_num – 店铺数
FROM
uc_store
WHERE
is_auth = 1
AND FROM_UNIXTIME(add_time) < ‘2020-11-01’
GROUP BY
areaid_1) store ON store.areaid_1 = area.area_id
LEFT JOIN – 各省份激活店铺数
(SELECT
store.areaid_1, – 省份id
SUM(CASE WHEN orders.order_amount >= 5000 THEN 1 ELSE 0 END) active_store – 激活店铺数
FROM
(SELECT
store_id, – 店铺id
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
store_id) orders
LEFT JOIN uc_store store ON store.store_id = orders.store_id
GROUP BY
store.areaid_1) active_s ON active_s.areaid_1 = area.area_id
WHERE
area_id < 32; – 过滤港澳台
3.2.3 编写python脚本
编写python脚本代码 daily_all_pf_orders.py,并将py文件上传到服务器
-- coding: UTF-8 --
import pandas as pd
from sqlalchemy import create_engine
import warnings
忽略警告
warnings.filterwarnings(‘ignore’)
创建mysql数据库链接
root:账号
123456:密码
192.168.88.100:ip地址
3306:端口号
shopnc_db:数据库名称
生产库链接
shopnc_engine = create_engine(‘mysql+pymysql://root:123456@192.168.88.100:3306/shopnc_db’)
BI库链接
bi_engine = create_engine(‘mysql+pymysql://root:123456@192.168.88.100:3306/BI_db’)
daily_all_pf_orders_sql = “”"
SELECT
area.area_name province, – 省份名称
IFNULL(dmonth.pf_order_sum, 0) pf_order_sum, – 当月订单数
IFNULL(tmonth.t_pf_order_sum, 0) t_pf_order_sum, – 上月同期订单数
IFNULL(dmonth.pf_order_amount, 0) pf_order_amount, – 当月订单总金额
IFNULL(tmonth.t_pf_order_amount, 0) t_pf_order_amount, – 上月同期订单总金额
IFNULL(dmonth.pf_order_chain_sum, 0) pf_order_chain_sum, – 当月下单门店数
IFNULL(tmonth.t_pf_order_chain_sum, 0) t_pf_order_chain_sum, – 上月同期下单门店数
IFNULL(dmonth.active_chain, 0) active_chain, – 门店激活数
IFNULL(dmonth.active_chain, 0) / chains.chain_num chain_active_ratio, – 门店激活率
IFNULL(active_s.active_store, 0) active_store, – 店铺激活数
IFNULL(active_s.active_store, 0) / store.store_num store_active_ratio, – 店铺激活率
CURDATE() collect_time – 统计时间
FROM
shopnc_area area
LEFT JOIN – 当月批发订单数据
(SELECT
chains.areaid_1, – 省份id
SUM(orders.order_num) pf_order_sum, – 订单数
SUM(orders.order_amount) pf_order_amount, – 订单总金额
COUNT(DISTINCT orders.buyer_id) pf_order_chain_sum, – 下单门店数
SUM(CASE WHEN orders.order_amount >= 1000 THEN 1 ELSE 0 END) active_chain – 激活门店数
FROM
(SELECT
buyer_id, – 门店会员id
COUNT(order_id) order_num, – 订单数
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3 – 批发订单
AND order_state IN (20, 30, 40) – 支付订单
GROUP BY buyer_id) orders
– 关联门店表,获取省份id
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
GROUP BY
chains.areaid_1) dmonth ON area.area_id = dmonth.areaid_1
LEFT JOIN – 上月同期批发订单数据
(SELECT
chains.areaid_1, – 省份id
COUNT(DISTINCT orders.order_id) t_pf_order_sum, – 同期订单数
SUM(orders.order_amount) t_pf_order_amount, – 同期订单总金额
COUNT(DISTINCT orders.buyer_id) t_pf_order_chain_sum – 同期下单门店数
FROM
shopnc_pf_orders orders
LEFT JOIN uc_chain chains ON chains.member_id = orders.buyer_id
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-09-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-10-01’
AND orders.order_type = 3
AND orders.order_state IN (20, 30, 40)
GROUP BY
chains.areaid_1) tmonth ON tmonth.areaid_1 = area.area_id
LEFT JOIN – 各省份门店总数
(SELECT
areaid_1, – 省份id
COUNT(DISTINCT chain_id) chain_num – 门店数
FROM
uc_chain
WHERE
is_auth = 1 – 认证门店
AND FROM_UNIXTIME(add_time) < ‘2020-11-01’
GROUP BY
areaid_1) chains ON chains.areaid_1 = area.area_id
LEFT JOIN – 各省份店铺总数
(SELECT
areaid_1, – 省份id
COUNT(DISTINCT store_id) store_num – 店铺数
FROM
uc_store
WHERE
is_auth = 1
AND FROM_UNIXTIME(add_time) < ‘2020-11-01’
GROUP BY
areaid_1) store ON store.areaid_1 = area.area_id
LEFT JOIN – 各省份激活店铺数
(SELECT
store.areaid_1, – 省份id
SUM(CASE WHEN orders.order_amount >= 5000 THEN 1 ELSE 0 END) active_store – 激活店铺数
FROM
(SELECT
store_id, – 店铺id
SUM(order_amount) order_amount – 订单总金额
FROM
shopnc_pf_orders
WHERE
FROM_UNIXTIME(payment_time) >= ‘2020-10-01’
AND FROM_UNIXTIME(payment_time) < ‘2020-11-01’
AND order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
store_id) orders
LEFT JOIN uc_store store ON store.store_id = orders.store_id
GROUP BY
store.areaid_1) active_s ON active_s.areaid_1 = area.area_id
WHERE
area_id < 32; – 过滤港澳台
“”"
daily_all_pf_orders_data = pd.read_sql(daily_all_pf_orders_sql, con=shopnc_engine)
daily_all_pf_orders_data.to_sql(“daily_all_pf_orders”, con=bi_engine, if_exists=“append”, index=False)
3.2.4 定时调度脚本
编写 finereport_project.sh shell脚本,执行python文件
/root/anaconda3/bin/python3 /root/finereport_file/daily_all_pf_orders.py &>> /root/finereport_file/log.txt
/root/anaconda3/bin/python3 /root/finereport_file/daily_all_pf_orders.py &>> /root/finereport_file/log.txt
使用linux服务器的crontab模块进行定时调度
crontab -e # 输入linux命令,编辑定时调用文件
将以下内容添加到文件中, 每天凌晨12点执行任务,跑数据
0 0 * * * /root/finereport_file/finereport_project.sh
3.2.5 制作需求报表
3.2.5.1 报表要求
报表展示 地区、当月批发订单数、同期批发订单数、当月批发订单总金额、同期批发订单总金额等字段
激活率百分比形式保留两位小数
报表默认显示当前日期的数据信息
可以实现筛选任意日期的数据信息
3.2.5.2 制作流程
新建数据集ds1,查询语句为SELECT * FROM daily_pf_orders
设计报表样式
依次将ds1中的字段拖拽到单元格A3~L3位置,添加如下报表标题和表头
合并第一行单元格,添加 xxx公司批发订单业务数据信息标题
将第一行单元格属性中样式修改为预定义样式,然后设置单元格居中、字体大小以及字体加粗
将A3单元格元素中的数据设置修改为列表
将I3和K3单元各属性中的文本格式修改为百分比,保留两位小数,四舍五入
将第一行和第二行设置重复与冻结
添加参数控件
添加模板参数,参数名修改为day,默认值修改为公式TODAY()
添加文本控件、日期控件和查询按钮
将文本控件的控件值修改为日期:
将日控件的控件名修改为day,和参数名相同,自动绑定参数
取消勾选para中的点击查询前不显示报表内容
添加过滤选项
双击A3单元格,选择过滤,可选列改为collect_time,值改为参数$day,点击增加
报表预览
先保存报表,然后点击分页预览,查看报表效果
3.2.5.3 报表部署
参考需求一中操作
3.3 统计各阶段门店用户数量
3.3.1 需求分析
业务人员需要每天查看公司不同阶段门店用户的数量,根据此数据来调整相关的运营策略。
需求字段如下:
未注册门店数:CRM系统中未注册的门店(未注册:is_register=0),门店状态为正常的 (正常:close_status=1)
未认证门店数:uc_chain, 已经注册但未提交认证的门店 (未提交认证:audit_status=0)
认证未通过门店数:uc_chain, 已经提交过认证,但认证被驳回的门店(认证被驳回:audit_status=3)
待激活门店数:认证通过,但未激活门店,门店激活逻辑为历史单月采购金额>1000元
活跃留存门店数:激活过并且最近两个月有过采购记录的门店
流失门店数:激活过并且最近两个月没有采购记录的门店
以上门店数总计
统计周期以天为单位进行统计,每天24点统计当天数据,可以支持按月筛选。本案例时间以2020-11-25为例进行统计
3.3.2 需求指标计算
CRM系统中客户表crm_customer
字段名 字段解释 字段说明
customer_id 客户自增id 没有实际意义
out_customer_id 电商门店/店铺id 门店和店铺存在客户表中
is_register 0未注册,1已注册 门店或店铺是否注册
customer_type 客户类型 0未知 1 门店 2 店铺 区分客户为门店还是店铺字段
close_status 关闭状态:门店:1正常 2关闭 / 店铺:0关闭,1开启,2审核中
add_time 添加时间 门店或店铺注册时间
…
CRM系统中未注册门店数
SELECT
COUNT(out_customer_id) AS unregistered
FROM
crm_customer
WHERE
date_format(add_time, ‘%Y-%m-%d’) <= ‘2020-11-25’
AND customer_type = 1 # 客户类型为门店
AND is_register = 0 # 未注册
AND close_status = 1; # 正常状态门店
未认证门店数和认证未通过门店数
统计门店状态为正常的门店
SELECT
COUNT(CASE WHEN audit_status = 0 THEN chain_id END) AS unverified, – 未认证
COUNT(CASE WHEN audit_status = 3 THEN chain_id END) AS unsanctioned – 认证未通过
FROM
uc_chain
WHERE
chain_status = 1 – 正常状态的门店
AND date_format(from_unixtime(add_time), ‘%Y-%m-%d’) <= ‘2020-11-25’;
待激活门店数、活跃留存门店数和流失门店数
历史单月采购金额大于1000元的门店即为激活门店
查询历史单月采购金额大于1000元的门店,会有重复门店,统计的是各门店每月的采购金额
SELECT
buyer_id,
SUM(order_amount) order_amount
FROM
shopnc_pf_orders
WHERE
payment_time <= UNIX_TIMESTAMP(‘2020-11-25’)
AND order_type = 3 – 批发订单
AND order_state IN (20, 30, 40) – 有效订单
GROUP BY
buyer_id, FROM_UNIXTIME(payment_time, ‘%Y-%m’)
HAVING
SUM(order_amount) > 1000;
激活门店id,激活门店去重
SELECT
orders.buyer_id
FROM
(SELECT
buyer_id,
SUM(order_amount) order_amount
FROM
shopnc_pf_orders
WHERE
payment_time <= UNIX_TIMESTAMP(‘2020-11-25’)
AND order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
buyer_id, FROM_UNIXTIME(payment_time, ‘%Y-%m’)
HAVING
SUM(order_amount) > 1000) orders
GROUP BY
orders.buyer_id;
查询近两个月有过购买记录的门店id
SELECT
buyer_id
FROM
shopnc_pf_orders
WHERE
order_type = 3
AND order_state IN (20, 30, 40)
AND payment_time <= UNIX_TIMESTAMP(‘2020-11-25’)
AND payment_time >= UNIX_TIMESTAMP(DATE_SUB(‘2020-11-25’, INTERVAL 2 MONTH))
GROUP BY
buyer_id;
待激活门店数、活跃留存门店数和流失门店数完整sql语句
门店表和激活门店子表以及有过购买记录门店子表关联,能关联上激活门店子表的说明是激活门店,关联不上为null值的就是待激活门店;同时能关联上购买记录门店子表的说明时激活过并且有采购的门店,关联不上为null值的就是激活过并且没有采购的门店
SELECT
COUNT(CASE WHEN orders1.buyer_id IS NULL THEN chains.chain_id END) AS unactivate, – 待激活门店数
COUNT(CASE
WHEN orders1.buyer_id IS NOT NULL AND orders2.buyer_id IS NOT NULL
THEN chains.chain_id END) AS activate, – 活跃留存门店数
COUNT(CASE
WHEN orders1.buyer_id IS NOT NULL AND orders2.buyer_id IS NULL
THEN chains.chain_id END) AS lose – 流失门店数
FROM
uc_chain chains
LEFT JOIN
(SELECT
orders.buyer_id
FROM
(SELECT
buyer_id,
SUM(order_amount) order_amount
FROM
shopnc_pf_orders
WHERE
payment_time <= UNIX_TIMESTAMP(‘2020-11-25’)
AND order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
buyer_id, FROM_UNIXTIME(payment_time, ‘%Y-%m’)
HAVING
SUM(order_amount) > 1000) orders
GROUP BY
orders.buyer_id) orders1 ON orders1.buyer_id = chains.member_id
LEFT JOIN
(SELECT
buyer_id
FROM
shopnc_pf_orders
WHERE
order_type = 3
AND order_state IN (20, 30, 40)
AND payment_time <= UNIX_TIMESTAMP(‘2020-11-25’)
AND payment_time >= UNIX_TIMESTAMP(DATE_SUB(‘2020-11-25’, INTERVAL 2 MONTH))
GROUP BY
buyer_id) orders2 ON orders2.buyer_id = chains.member_id
WHERE
chains.chain_status = 1
AND chains.is_auth = 1;
需求完整sql
SELECT
chains1.unregistered, – 未注册门店数(crm中)
chains2.unverified, – 未认证门店数
chains2.unsanctioned, – 认证未通过门店数
chains3.unactivate, – 待激活门店数
chains3.activate, – 活跃留存门店数
chains3.lose, – 流失门店数
‘2020-11-25’ date_time
FROM
(-- crm未注册门店数
SELECT
COUNT(out_customer_id) AS unregistered
FROM
crm_customer
WHERE
date_format(add_time, ‘%Y-%m-%d’) <= ‘2020-11-25’
AND customer_type = 1
AND is_register = 0
AND company_id = 1
AND close_status = 1) chains1,
– 未认证:已经注册提交认证的门店数
– 认证未通过:已经提交过认证但认证驳回的门店数
(SELECT
COUNT(CASE WHEN audit_status = 0 THEN chain_id END) AS unverified, – 未认证
COUNT(CASE WHEN audit_status = 3 THEN chain_id END) AS unsanctioned – 认证未通过
FROM
uc_chain
WHERE
chain_status = 1
AND date_format(from_unixtime(add_time), ‘%Y-%m-%d’) <= ‘2020-11-25’) chains2,
– 待激活:认证通过但待激活(单月采购金额>=1000元)的门店数
– 激活过且近2个月有采购
– 激活过且近2个月未采购
(SELECT
COUNT(CASE WHEN orders1.buyer_id IS NULL THEN chains.chain_id END) AS unactivate, – 待激活门店数
COUNT(CASE
WHEN orders1.buyer_id IS NOT NULL AND orders2.buyer_id IS NOT NULL
THEN chains.chain_id END) AS activate, – 活跃留存门店数
COUNT(CASE
WHEN orders1.buyer_id IS NOT NULL AND orders2.buyer_id IS NULL
THEN chains.chain_id END) AS lose – 流失门店数
FROM
uc_chain chains
LEFT JOIN
(SELECT
orders.buyer_id
FROM
(SELECT
buyer_id,
SUM(order_amount) order_amount
FROM
shopnc_pf_orders
WHERE
order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
buyer_id, FROM_UNIXTIME(payment_time, ‘%Y-%m’)
HAVING
SUM(order_amount) > 1000) orders
GROUP BY
orders.buyer_id) orders1 ON orders1.buyer_id = chains.member_id
LEFT JOIN
(SELECT
buyer_id
FROM
shopnc_pf_orders
WHERE
order_type = 3
AND order_state IN (20, 30, 40)
AND payment_time <= UNIX_TIMESTAMP(‘2020-11-25’)
AND payment_time >= UNIX_TIMESTAMP(DATE_SUB(‘2020-11-25’, INTERVAL 2 MONTH))
GROUP BY
buyer_id) orders2 ON orders2.buyer_id = chains.member_id
WHERE
chains.chain_status = 1
AND chains.is_auth = 1) chains3;
3.3.3 报表数据保存到mysql数据库
创建daily_stage_chain表
CREATE TABLE IF NOT EXISTS daily_stage_chain
(
id INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘主键id’,
unregistered INT COMMENT ‘CRM系统中未注册门店数’,
unverified INT COMMENT ‘未认证门店数’,
unsanctioned INT COMMENT ‘认证未通过门店数’,
unactivate INT COMMENT ‘待激活门店数’,
activate INT COMMENT ‘激活门店数’,
lose INT COMMENT ‘流失门店数’,
collect_time DATE COMMENT ‘统计日期’
);
向表中插入数据
INSERT INTO daily_stage_chain
SELECT
NULL,
chains1.unregistered, – 未注册门店数(crm中)
chains2.unverified, – 未认证门店数
chains2.unsanctioned, – 认证未通过门店数
chains3.unactivate, – 待激活门店数
chains3.activate, – 活跃留存门店数
chains3.lose, – 流失门店数
‘2020-11-25’ collect_time
FROM
(-- crm未注册门店数
SELECT
COUNT(out_customer_id) AS unregistered
FROM
crm_customer
WHERE
date_format(add_time, ‘%Y-%m-%d’) <= ‘2020-11-25’
AND customer_type = 1
AND is_register = 0
AND company_id = 1
AND close_status = 1) chains1,
– 未认证:已经注册提交认证的门店数
– 认证未通过:已经提交过认证但认证驳回的门店数
(SELECT
COUNT(CASE WHEN audit_status = 0 THEN chain_id END) AS unverified, – 未认证
COUNT(CASE WHEN audit_status = 3 THEN chain_id END) AS unsanctioned – 认证未通过
FROM
uc_chain
WHERE
chain_status = 1
AND date_format(from_unixtime(add_time), ‘%Y-%m-%d’) <= ‘2020-11-25’) chains2,
– 待激活:认证通过但待激活(单月采购金额>=1000元)的门店数
– 激活过且近2个自然月(不包含当月)有采购
– 激活过且近2个自然月(不包含当月)未采购
(SELECT
COUNT(CASE WHEN orders1.buyer_id IS NULL THEN chains.chain_id END) AS unactivate, – 待激活门店数
COUNT(CASE
WHEN orders1.buyer_id IS NOT NULL AND orders2.buyer_id IS NOT NULL
THEN chains.chain_id END) AS activate, – 活跃留存门店数
COUNT(CASE
WHEN orders1.buyer_id IS NOT NULL AND orders2.buyer_id IS NULL
THEN chains.chain_id END) AS lose – 流失门店数
FROM
uc_chain chains
LEFT JOIN
(SELECT
orders.buyer_id
FROM
(SELECT
buyer_id,
SUM(order_amount) order_amount
FROM
shopnc_pf_orders
WHERE
order_type = 3
AND order_state IN (20, 30, 40)
GROUP BY
buyer_id, FROM_UNIXTIME(payment_time, ‘%Y-%m’)
HAVING
SUM(order_amount) > 1000) orders
GROUP BY
orders.buyer_id) orders1 ON orders1.buyer_id = chains.member_id
LEFT JOIN
(SELECT
buyer_id
FROM
shopnc_pf_orders
WHERE
order_type = 3
AND order_state IN (20, 30, 40)
AND payment_time <= UNIX_TIMESTAMP(‘2020-11-25’)
AND payment_time >= UNIX_TIMESTAMP(DATE_SUB(‘2020-11-25’, INTERVAL 2 MONTH))
GROUP BY
buyer_id) orders2 ON orders2.buyer_id = chains.member_id
WHERE
chains.chain_status = 1
AND chains.is_auth = 1) chains3;
3.3.4 制作需求报表
3.3.4.1 报表要求
报表展示 未注册门店数、未认证门店数、认证未通过门店数、待激活门店数、活跃留存门店数、流失门店数、门店总数 以及 统计日期
可以实现按月筛选数据,默认展示所有数据
3.3.4.2 制作流程
新建数据集ds1,查询语句为 SELECT * FROM daily_stage_chain where 1=1 ${if(len(month)==0,“”,“and date_format(collect_time, ‘%Y-%m’) = '” + month + “'”)}
新建ds2数据集,查询语句为 SELECT date_format(collect_time, ‘%Y-%m’) month FROMdaily_stage_chaingroup by date_format(collect_time, ‘%Y-%m’)
设计报表样式
依次将ds1中的字段拖拽到单元格A3~G3位置,添加如下报表标题和表头
合并第一行单元格,添加 xxx公司各阶段用户数量报表标题
将第一行单元格属性中样式修改为预定义样式,然后设置单元格居中、字体大小以及字体加粗
将A3单元格元素中的数据设置修改为列表
将第一行和第二行设置重复与冻结
添加参数控件
添加文本控件,控件值修改为 年月:
添加下拉框控件
控件名称修改为month,数据字典中类型设置选择数据查询,数据集选择ds2,实际值和显示值都选择month列
添加查询按钮
取消勾选para组件中 点击查询前不显示报表内容
保存报表,点击分页预览,查看报表显示效果
3.3.4.3 报表部署
参考需求一中操作
3.4 统计erp系统各公司销售订单数据
3.4.1 需求分析
业务人员需要通过erp系统中各公司当月和上月同期销售订单数据分析,制定相关的运营措施,需求指标字段信息如下:
erp系统中公司名称:erp_name
公司所在省份:area_name
当月订单数:erp_order_id 计数
上月同期订单数:erp_order_id 计数
订单数增长率:(当月-上月)/ 上月,以百分比形式展示,保留两位小数
当月已付款订单数:order_state=20的订单
当月已发货订单数:order_state=30的订单
当月已收货订单数:order_state=40的订单
当月订单总金额:erp_order_amount 求和
上月同期订单总金额:erp_order_amount 求和
订单总金额增长率:(当月-上月)/ 上月,以百分比形式展示,保留两位小数
当月下单门店数:erp_buyer_id 去重计数
上月同期下单门店数:erp_buyer_id 去重计数
下单门店数增长率:(当月-上月)/ 上月,以百分比形式展示,保留两位小数
统计日期:保留年月
统计周期以月为单位进行统计,每天24点统计当月数据,可以支持按月筛选。本案例时间以2020-11为例进行统计
3.4.2 需求指标计算
erp系统公司表 shopnc_erp
字段名 字段解释 字段说明
erp_id 归属erp公司id erp系统中的公司id
erp_name erp公司名称 erp系统中的公司名称
area_id_1 区域省份id 和area地区表关联的省份id
erp系统订单表 shopnc_erp_order
字段名 字段解释 字段说明
erp_order_id erp订单主键 订单id
erp_store_id 电商店铺id 店铺表中的店铺id
erp_store_name 电商店铺名称 店铺表中的店铺名称
erp_buyer_id 电商门店chain_id 门店表中的门店id
erp_buyer_name 电商门店chain_name 门店表中的门店名称
erp_order_amount 订单总金额
add_time erp订单生成时间
payment_time erp订单支付时间
erp_id 归属erp id erp系统公司表中的公司id
order_state 电商标准的订单状态 与shopnc_pf_orders表中order_state字段 相同
erp_refund_state 退单状态 0:未退单 1:退单
area_1 省份id
查询erp系统中各公司的公司id,公司名称,公司所在省份
SELECT
erp.erp_id, – 公司id
erp_name, – 公司名称
area.area_name – 公司所在省份
FROM
shopnc_erp erp
LEFT JOIN shopnc_area area ON erp.area_id_1 = area_id;
查询当月2020-11 erp系统中订单相关数据:公司id,下单门店数,订单数量,订单总金额,已付款订单数量,已发货订单数量,已收货订单数量
不包含测试店铺门店订单以及退款订单,查询时间以订单支付时间为准,订单状态以20、30、40为准
SELECT
erp.erp_id, – 公司id
COUNT(DISTINCT erp_buyer_id) AS chain_count, – 下单门店数
COUNT(*) AS order_count, – 订单数量
COUNT(CASE WHEN order_state = 20 THEN erp_order_id END) AS pay_order_count, – 已付款订单数
COUNT(CASE WHEN order_state = 30 THEN erp_order_id END) AS send_order_count, – 已发货订单数
COUNT(CASE WHEN order_state = 40 THEN erp_order_id END) AS get_order_count, – 已收货订单数
SUM(erp_order_amount) AS order_amount – 订单总金额
FROM
shopnc_erp_order
AS erp_order
LEFT JOIN shopnc_erp
AS erp
ON erp_order.erp_id = erp.erp_id
WHERE
FROM_UNIXTIME(payment_time, ‘%Y-%m’) = ‘2020-11’
AND erp_store_name NOT LIKE ‘%测试%’
AND erp_buyer_name NOT LIKE ‘%测试%’
AND order_state IN (‘20’, ‘30’, ‘40’)
AND erp_order.erp_refund_state <> ‘1’
GROUP BY
erp.erp_id;
查询上月2020-10 erp系统中订单相关数据:公司id,下单门店数,订单数量,订单总金额,已付款订单数量,已发货订单数量,已收货订单数量
不包含测试店铺门店订单以及退款订单,查询时间以订单支付时间为准,订单状态以20、30、40为准
SELECT
erp.erp_id,
COUNT(DISTINCT erp_buyer_name) AS chain_count,
COUNT(*) AS order_count,
COUNT(CASE WHEN order_state = 20 THEN erp_order_id END) AS pay_order_count,
COUNT(CASE WHEN order_state = 30 THEN erp_order_id END) AS send_order_count,
COUNT(CASE WHEN order_state = 40 THEN erp_order_id END) AS get_order_count,
SUM(erp_order_amount) AS order_amount
FROM
shopnc_erp_order
AS erp_order
LEFT JOIN shopnc_erp
AS erp
ON erp_order.erp_id = erp.erp_id
WHERE
FROM_UNIXTIME(payment_time, ‘%Y-%m’) = ‘2020-10’
AND erp_store_name NOT LIKE ‘%测试%’
AND erp_buyer_name NOT LIKE ‘%测试%’
AND order_state IN (‘20’, ‘30’, ‘40’)
AND erp_order.erp_refund_state <> ‘1’
GROUP BY
erp.erp_id;
完整查询sql
SELECT
erp_name,
area_name,
dmonth.order_count erp_order_sum,
tmonth.order_count t_erp_order_sum,
CONCAT(ROUND((dmonth.order_count - tmonth.order_count) / tmonth.order_count * 100, 2), ‘%’) order_sum_percent, – 订单增长率
dmonth.pay_order_count,
dmonth.send_order_count,
dmonth.get_order_count,
dmonth.order_amount erp_order_amount,
tmonth.order_amount t_erp_order_amount,
CONCAT(ROUND((dmonth.order_amount - tmonth.order_amount) / tmonth.order_amount * 100, 2), ‘%’) order_amount_percent, – 订单总金额增长率
dmonth.chain_count erp_order_chain_sum,
tmonth.chain_count t_erp_order_chain_sum,
CONCAT(ROUND((dmonth.chain_count - tmonth.chain_count) / tmonth.chain_count * 100, 2), ‘%’) chain_sum_percent, – 下单门店增长率
‘2020-11-28’ as date_time
FROM
(SELECT
erp.erp_id,
erp.erp_name,
area.area_name
FROM
shopnc_erp erp
LEFT JOIN shopnc_area area ON erp.area_id_1 = area_id) erp
LEFT JOIN
(SELECT
erp.erp_id,
COUNT(DISTINCT erp_buyer_name) AS chain_count,
COUNT() AS order_count,
COUNT(CASE WHEN order_state = 20 THEN erp_order_id END) AS pay_order_count,
COUNT(CASE WHEN order_state = 30 THEN erp_order_id END) AS send_order_count,
COUNT(CASE WHEN order_state = 40 THEN erp_order_id END) AS get_order_count,
SUM(erp_order_amount) AS order_amount
FROM
shopnc_erp_order AS erp_order
LEFT JOIN shopnc_erp AS erp ON erp_order.erp_id = erp.erp_id
WHERE
FROM_UNIXTIME(payment_time, ‘%Y-%m’) = ‘2020-11’
AND erp_store_name NOT LIKE ‘%测试%’
AND erp_buyer_name NOT LIKE ‘%测试%’
AND order_state IN (‘20’, ‘30’, ‘40’)
AND erp_order.erp_refund_state <> ‘1’
GROUP BY
erp.erp_id) dmonth ON dmonth.erp_id = erp.erp_id
LEFT JOIN
(SELECT
erp.erp_id,
COUNT(DISTINCT erp_buyer_name) AS chain_count,
COUNT() AS order_count,
SUM(erp_order_amount) AS order_amount
FROM
shopnc_erp_order AS erp_order
LEFT JOIN shopnc_erp AS erp ON erp_order.erp_id = erp.erp_id
WHERE
FROM_UNIXTIME(payment_time, ‘%Y-%m’) = ‘2020-10’
AND erp_store_name NOT LIKE ‘%测试%’
AND erp_buyer_name NOT LIKE ‘%测试%’
AND order_state IN (‘20’, ‘30’, ‘40’)
AND erp_order.erp_refund_state <> ‘1’
GROUP BY
erp.erp_id) tmonth ON tmonth.erp_id = erp.erp_id;
3.4.3 报表数据保存到mysql数据库
创建daily_erp_orders表
CREATE TABLE IF NOT EXISTS daily_erp_orders
(
id INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘主键字段id’,
erp_name VARCHAR(256) COMMENT ‘公司名称’,
area_name VARCHAR(20) COMMENT ‘省份’,
erp_order_sum INT DEFAULT 0 COMMENT ‘当月订单数量’,
t_erp_order_sum INT DEFAULT 0 COMMENT ‘上月同期订单数量’,
order_sum_percent VARCHAR(10) DEFAULT 0 COMMENT ‘订单增长率’,
pay_order_count INT DEFAULT 0 COMMENT ‘当月已付款订单数’,
send_order_count INT DEFAULT 0 COMMENT ‘当月已发货订单数’,
get_order_count INT DEFAULT 0 COMMENT ‘当月已收货订单数’,
erp_order_amount DOUBLE DEFAULT 0.00 COMMENT ‘当月订单总金额’,
t_erp_order_amount DOUBLE DEFAULT 0.00 COMMENT ‘上月同期订单总金额’,
order_amount_percent VARCHAR(10) DEFAULT 0 COMMENT ‘订单总金额增长率’,
erp_order_chain_sum INT DEFAULT 0 COMMENT ‘当月下单门店数’,
t_erp_order_chain_sum INT DEFAULT 0 COMMENT ‘上月同期下单门店数’,
chain_sum_percent VARCHAR(10) DEFAULT 0 COMMENT ‘下单门店数增长率’,
collect_time DATE COMMENT ‘统计日期’
);
向表中插入数据
INSERT INTO
daily_erp_orders
SELECT
NULL,
erp_name,
area_name,
dmonth.order_count erp_order_sum,
tmonth.order_count t_erp_order_sum,
CONCAT(ROUND((dmonth.order_count - tmonth.order_count) / tmonth.order_count * 100, 2), ‘%’) order_sum_percent,
dmonth.pay_order_count,
dmonth.send_order_count,
dmonth.get_order_count,
dmonth.order_amount erp_order_amount,
tmonth.order_amount t_erp_order_amount,
CONCAT(ROUND((dmonth.order_amount - tmonth.order_amount) / tmonth.order_amount * 100, 2), ‘%’) order_amount_percent,
dmonth.chain_count erp_order_chain_sum,
tmonth.chain_count t_erp_order_chain_sum,
CONCAT(ROUND((dmonth.chain_count - tmonth.chain_count) / tmonth.chain_count * 100, 2), ‘%’) chain_sum_percent,
‘2020-11-28’ AS date_time
FROM
(SELECT
erp.erp_id,
erp.erp_name,
area.area_name
FROM
shopnc_erp erp
LEFT JOIN shopnc_area area ON erp.area_id_1 = area_id) erp
LEFT JOIN
(SELECT
erp.erp_id,
COUNT(DISTINCT erp_buyer_name) AS chain_count,
COUNT() AS order_count,
COUNT(CASE WHEN order_state = 20 THEN erp_order_id END) AS pay_order_count,
COUNT(CASE WHEN order_state = 30 THEN erp_order_id END) AS send_order_count,
COUNT(CASE WHEN order_state = 40 THEN erp_order_id END) AS get_order_count,
SUM(erp_order_amount) AS order_amount
FROM
shopnc_erp_order AS erp_order
LEFT JOIN shopnc_erp AS erp ON erp_order.erp_id = erp.erp_id
WHERE
FROM_UNIXTIME(payment_time, ‘%Y-%m’) = ‘2020-11’
AND erp_store_name NOT LIKE ‘%测试%’
AND erp_buyer_name NOT LIKE ‘%测试%’
AND order_state IN (‘20’, ‘30’, ‘40’)
AND erp_order.erp_refund_state <> ‘1’
GROUP BY
erp.erp_id) dmonth ON dmonth.erp_id = erp.erp_id
LEFT JOIN
(SELECT
erp.erp_id,
COUNT(DISTINCT erp_buyer_name) AS chain_count,
COUNT() AS order_count,
SUM(erp_order_amount) AS order_amount
FROM
shopnc_erp_order AS erp_order
LEFT JOIN shopnc_erp AS erp ON erp_order.erp_id = erp.erp_id
WHERE
FROM_UNIXTIME(payment_time, ‘%Y-%m’) = ‘2020-10’
AND erp_store_name NOT LIKE ‘%测试%’
AND erp_buyer_name NOT LIKE ‘%测试%’
AND order_state IN (‘20’, ‘30’, ‘40’)
AND erp_order.erp_refund_state <> ‘1’
GROUP BY
erp.erp_id) tmonth ON tmonth.erp_id = erp.erp_id;
3.4.4 制作需求报表
3.4.4.1 报表要求
展示业务方需要的所有指标数据
可以实现按天进行查询,一次可以查询多天的数据
默认显示报表中的所有数据
3.4.4.2 制作流程
新建数据集ds1,查询语句为SELECT * FROM daily_erp_orders where 1=1 ${if(len(day)==0,“”,“and collect_time in ('” + day + “')”)}
新建数据集ds2,查询语句为SELECT collect_time FROM daily_erp_orders group by collect_time
设计报表样式
依次将ds1中的字段拖拽到单元格A3~03位置,添加如下报表标题和表头
调整报表页面大小
合并第一行单元格,添加 xxx公司erp系统订单数据报表标题
将第一行单元格属性中样式修改为预定义样式,然后设置单元格居中、字体大小以及字体加粗
将A3单元格元素中的数据设置修改为列表
将第一行和第二行设置重复与冻结
添加控件参数
添加文本控件,控件值修改为日期:
添加下拉复选框控件,控件名称修改为day,数据字典中类型设置选择数据查询,数据集选择ds2,实际值和显示值选择collect_time列,返回值类型选择字符串,分隔符修改为’,’
添加查询按钮组件
取消勾选para组件中 点击查询前不显示报表内容
保存报表,点击分页预览,查看报表显示效果
3.4.4.3 报表部署
参考需求一中操作
3.5 统计各品牌代理店签约动销门店数据
3.5.1 需求分析
业务人员需要查看每天品牌代理店活动中的签约门店数和动销门店数,进行后续的数据分析工作。需要统计九大品牌代理店的数据信息,统计指标如下:
签约门店数(门店去重)
动销门店数(动销:签约门店产生过订单)
签约门店总数
动销门店总数
统计日期
需要统计九大品牌代理店每天的信息,保存到数据库中,然后制作成报表,以便业务人员随时查看。
3.5.2 需求指标计算
品牌代理店门店签约表 daily_operate_agent_brand_name
字段名 字段解释 字段说明
investment_id 招商活动id 除49、54、55、58、69活动外,其他都是品牌代理店活动
investment_name 招商活动名称 品牌代理店名称
chain_id 门店id 签约活动的门店id
state 招商活动状态 待审核,已通过,拒绝 统计数据为招商活动活动状态已通过的门店
date_join_time 活动通过时间 签约门店数以此时间为准
品牌代理店门店动销表 agent_passenger_performance_brand_agency_pfdetail
字段名 字段解释 字段说明
investment_id 招商活动id 除49、54、55、58、69活动外,其他都是品牌代理店活动
chain_id 门店id 动销门店的门店id
type 类型:1,3,5:品牌代理店订单;2,4,6:卫星门店订单 统计数据以1、3、5为准
payment_time 订单支付时间 动销门店数以此时间为准
获取九大品牌代理店招商活动名
– 需求是要统计九大品牌代理店每天的数据信息
– 如果只从两张表中统计数据,九大品牌代理店并不是每天都有数据产生
– 所以要先拿到九大品牌代理店活动名称然后再与每天统计的数据进行管理,这样保证都能查询到九大品牌代理店数据
SELECT
‘TOP辐驰润滑油品牌代理店招商’ type
UNION
SELECT
‘康斯创达轮胎品牌代理店招商’
UNION
SELECT
‘辐驰易损件品牌代理店招商’
UNION
SELECT
‘辐驰润滑油品牌代理店招商’
UNION
SELECT
‘辐驰轮胎品牌代理店招商’
UNION
SELECT
‘辐驰轮胎区域合伙人’
UNION
SELECT
‘邓禄普轮胎品牌代理店招商’
UNION
SELECT
‘锦湖轮胎品牌代理店招商’
UNION
SELECT
‘飞劲轮胎品牌代理店招商’;
统计九大品牌代理店活动签约门店数
– 以2020-12-03日期进行统计
SELECT
investment_name, – 活动名称
COUNT(DISTINCT chain_id) sign_chain_num – 活动签约门店数
FROM
daily_operate_agent_brand_name
WHERE
state = ‘已通过’ – 签约状态
AND date_join_time = ‘2020-12-03’ – 通过时间
GROUP BY
investment_name;
统计九大品牌代理店活动动销门店数
SELECT
investment_name,
COUNT(DISTINCT chain_id) sale_chain_num – 动销门店数
FROM
agent_passenger_performance_brand_agency_pfdetail
WHERE
type IN (1, 3, 5) – 品牌代理店
AND payment_time = ‘2020-12-03’
GROUP BY
investment_name;
统计九大品牌代理店活动的签约门店数和动销门店数
– type值等于investment_name值
– 查询的数据一共有四个字段,活动名称,签约门店数,动销门店数,统计日期
SELECT
chain1.type,
IFNULL(chain2.sign_chain_num, 0) sign_chain_num,
IFNULL(chain3.sale_chain_num, 0) sale_chain_num,
‘2020-12-03’ collect_time
FROM
(SELECT
‘TOP辐驰润滑油品牌代理店招商’ type
UNION
SELECT
‘康斯创达轮胎品牌代理店招商’
UNION
SELECT
‘辐驰易损件品牌代理店招商’
UNION
SELECT
‘辐驰润滑油品牌代理店招商’
UNION
SELECT
‘辐驰轮胎品牌代理店招商’
UNION
SELECT
‘辐驰轮胎区域合伙人’
UNION
SELECT
‘邓禄普轮胎品牌代理店招商’
UNION
SELECT
‘锦湖轮胎品牌代理店招商’
UNION
SELECT
‘飞劲轮胎品牌代理店招商’) chain1
LEFT JOIN
(SELECT
investment_name,
COUNT(DISTINCT chain_id) sign_chain_num
FROM
daily_operate_agent_brand_name
WHERE
state = ‘已通过’
AND date_join_time = ‘2020-12-03’
GROUP BY
investment_name) chain2 ON chain2.investment_name = chain1.type
LEFT JOIN
(SELECT
investment_name,
COUNT(DISTINCT chain_id) sale_chain_num
FROM
agent_passenger_performance_brand_agency_pfdetail
WHERE
type IN (1, 3, 5)
AND payment_time = ‘2020-12-03’
GROUP BY
investment_name) chain3 ON chain3.investment_name = chain1.type
行列进行转置,查询每个品牌代理店活动的签约门店数和动销门店数以及统计日期
– case…when…语法查询出每个品牌代理店活动的数据
– 以统计日期分组,结合max()聚合函数,实现行列转置操作
SELECT
collect_time,
MAX(CASE chains.type WHEN “TOP辐驰润滑油品牌代理店招商” THEN chains.sign_chain_num END) sign_1,
MAX(CASE chains.type WHEN “康斯创达轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_2,
MAX(CASE chains.type WHEN “辐驰易损件品牌代理店招商” THEN chains.sign_chain_num END) sign_3,
MAX(CASE chains.type WHEN “辐驰润滑油品牌代理店招商” THEN chains.sign_chain_num END) sign_4,
MAX(CASE chains.type WHEN “辐驰轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_5,
MAX(CASE chains.type WHEN “辐驰轮胎区域合伙人” THEN chains.sign_chain_num END) sign_6,
MAX(CASE chains.type WHEN “邓禄普轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_7,
MAX(CASE chains.type WHEN “锦湖轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_8,
MAX(CASE chains.type WHEN “飞劲轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_9,
MAX(CASE chains.type WHEN “TOP辐驰润滑油品牌代理店招商” THEN chains.sale_chain_num END) sale_1,
MAX(CASE chains.type WHEN “康斯创达轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_2,
MAX(CASE chains.type WHEN “辐驰易损件品牌代理店招商” THEN chains.sale_chain_num END) sale_3,
MAX(CASE chains.type WHEN “辐驰润滑油品牌代理店招商” THEN chains.sale_chain_num END) sale_4,
MAX(CASE chains.type WHEN “辐驰轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_5,
MAX(CASE chains.type WHEN “辐驰轮胎区域合伙人” THEN chains.sale_chain_num END) sale_6,
MAX(CASE chains.type WHEN “邓禄普轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_7,
MAX(CASE chains.type WHEN “锦湖轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_8,
MAX(CASE chains.type WHEN “飞劲轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_9
FROM
(SELECT
chain1.type,
IFNULL(chain2.sign_chain_num, 0) sign_chain_num,
IFNULL(chain3.sale_chain_num, 0) sale_chain_num,
‘2020-12-03’ collect_time
FROM
(SELECT
‘TOP辐驰润滑油品牌代理店招商’ type
UNION
SELECT
‘康斯创达轮胎品牌代理店招商’
UNION
SELECT
‘辐驰易损件品牌代理店招商’
UNION
SELECT
‘辐驰润滑油品牌代理店招商’
UNION
SELECT
‘辐驰轮胎品牌代理店招商’
UNION
SELECT
‘辐驰轮胎区域合伙人’
UNION
SELECT
‘邓禄普轮胎品牌代理店招商’
UNION
SELECT
‘锦湖轮胎品牌代理店招商’
UNION
SELECT
‘飞劲轮胎品牌代理店招商’) chain1
LEFT JOIN
(SELECT
investment_name,
COUNT(DISTINCT chain_id) sign_chain_num
FROM
daily_operate_agent_brand_name
WHERE
state = ‘已通过’
AND date_join_time = ‘2020-12-03’
GROUP BY
investment_name) chain2 ON chain2.investment_name = chain1.type
LEFT JOIN
(SELECT
investment_name,
COUNT(DISTINCT chain_id) sale_chain_num
FROM
agent_passenger_performance_brand_agency_pfdetail
WHERE
type IN (1, 3, 5)
AND payment_time = ‘2020-12-03’
GROUP BY
investment_name) chain3 ON chain3.investment_name = chain1.type) chains
GROUP BY
chains.collect_time;
3.5.3 报表数据保存到mysql数据库
创建daily_brand_chains表
CREATE TABLE IF NOT EXISTS daily_brand_chains
(
collect_time DATE COMMENT ‘统计日期’,
sign_1 INT COMMENT ‘TOP辐驰润滑油品牌代理店招商签约门店数’,
sign_2 INT COMMENT ‘康斯创达轮胎品牌代理店招商签约门店数’,
sign_3 INT COMMENT ‘辐驰易损件品牌代理店招商签约门店数’,
sign_4 INT COMMENT ‘辐驰润滑油品牌代理店招商签约门店数’,
sign_5 INT COMMENT ‘辐驰轮胎品牌代理店招商签约门店数’,
sign_6 INT COMMENT ‘辐驰轮胎区域合伙人签约门店数’,
sign_7 INT COMMENT ‘邓禄普轮胎品牌代理店招商签约门店数’,
sign_8 INT COMMENT ‘锦湖轮胎品牌代理店招商签约门店数’,
sign_9 INT COMMENT ‘飞劲轮胎品牌代理店招商签约门店数’,
sale_1 INT COMMENT ‘TOP辐驰润滑油品牌代理店招商动销门店数’,
sale_2 INT COMMENT ‘康斯创达轮胎品牌代理店招商动销门店数’,
sale_3 INT COMMENT ‘辐驰易损件品牌代理店招商动销门店数’,
sale_4 INT COMMENT ‘辐驰润滑油品牌代理店招商动销门店数’,
sale_5 INT COMMENT ‘辐驰轮胎品牌代理店招商动销门店数’,
sale_6 INT COMMENT ‘辐驰轮胎区域合伙人动销门店数’,
sale_7 INT COMMENT ‘邓禄普轮胎品牌代理店招商动销门店数’,
sale_8 INT COMMENT ‘锦湖轮胎品牌代理店招商动销门店数’,
sale_9 INT COMMENT ‘飞劲轮胎品牌代理店招商动销门店数’
);
向表中插入数据
INSERT INTO
daily_brand_chains
SELECT
collect_time,
MAX(CASE chains.type WHEN “TOP辐驰润滑油品牌代理店招商” THEN chains.sign_chain_num END) sign_1,
MAX(CASE chains.type WHEN “康斯创达轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_2,
MAX(CASE chains.type WHEN “辐驰易损件品牌代理店招商” THEN chains.sign_chain_num END) sign_3,
MAX(CASE chains.type WHEN “辐驰润滑油品牌代理店招商” THEN chains.sign_chain_num END) sign_4,
MAX(CASE chains.type WHEN “辐驰轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_5,
MAX(CASE chains.type WHEN “辐驰轮胎区域合伙人” THEN chains.sign_chain_num END) sign_6,
MAX(CASE chains.type WHEN “邓禄普轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_7,
MAX(CASE chains.type WHEN “锦湖轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_8,
MAX(CASE chains.type WHEN “飞劲轮胎品牌代理店招商” THEN chains.sign_chain_num END) sign_9,
MAX(CASE chains.type WHEN “TOP辐驰润滑油品牌代理店招商” THEN chains.sale_chain_num END) sale_1,
MAX(CASE chains.type WHEN “康斯创达轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_2,
MAX(CASE chains.type WHEN “辐驰易损件品牌代理店招商” THEN chains.sale_chain_num END) sale_3,
MAX(CASE chains.type WHEN “辐驰润滑油品牌代理店招商” THEN chains.sale_chain_num END) sale_4,
MAX(CASE chains.type WHEN “辐驰轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_5,
MAX(CASE chains.type WHEN “辐驰轮胎区域合伙人” THEN chains.sale_chain_num END) sale_6,
MAX(CASE chains.type WHEN “邓禄普轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_7,
MAX(CASE chains.type WHEN “锦湖轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_8,
MAX(CASE chains.type WHEN “飞劲轮胎品牌代理店招商” THEN chains.sale_chain_num END) sale_9
FROM
(SELECT
chain1.type,
IFNULL(chain2.sign_chain_num, 0) sign_chain_num,
IFNULL(chain3.sale_chain_num, 0) sale_chain_num,
‘2020-12-04’ collect_time
FROM
(SELECT
‘TOP辐驰润滑油品牌代理店招商’ type
UNION
SELECT
‘康斯创达轮胎品牌代理店招商’
UNION
SELECT
‘辐驰易损件品牌代理店招商’
UNION
SELECT
‘辐驰润滑油品牌代理店招商’
UNION
SELECT
‘辐驰轮胎品牌代理店招商’
UNION
SELECT
‘辐驰轮胎区域合伙人’
UNION
SELECT
‘邓禄普轮胎品牌代理店招商’
UNION
SELECT
‘锦湖轮胎品牌代理店招商’
UNION
SELECT
‘飞劲轮胎品牌代理店招商’) chain1
LEFT JOIN
(SELECT
investment_name,
COUNT(DISTINCT chain_id) sign_chain_num
FROM
daily_operate_agent_brand_name
WHERE
state = ‘已通过’
AND date_join_time = ‘2020-12-04’
GROUP BY
investment_name) chain2 ON chain2.investment_name = chain1.type
LEFT JOIN
(SELECT
investment_name,
COUNT(DISTINCT chain_id) sale_chain_num
FROM
agent_passenger_performance_brand_agency_pfdetail
WHERE
type IN (1, 3, 5)
AND payment_time = ‘2020-12-04’
GROUP BY
investment_name) chain3 ON chain3.investment_name = chain1.type) chains
GROUP BY
chains.collect_time;
3.5.4 制作需求报表
3.5.4.1 报表要求
展示业务方需要的所有指标数据
以天为统计单位,统计每天九大品牌代理店活动的数据
报表可以实现按月查询,默认展示当前月的所有数据 (format(today(), ‘yyyy-MM’))
3.5.4.2 制作流程
新建数据ds1,查询语句为 SELECT * FROMdaily_brand_chainswhere 1=1 ${if(len(month)==0,“”,“and date_format(collect_time, ‘%Y-%m’) = '” + month + “'”)} order by collect_time desc;
新建数据ds2,查询语句为 SELECT date_format(collect_time, ‘%Y-%m’) month FROM daily_brand_chains group by date_format(collect_time, ‘%Y-%m’);
设计报表样式
依次将ds1中的字段拖拽到单元格A3~U3位置,添加如下报表标题和表头
调整报表页面大小
合并第一行单元格,添加 xxx公司品牌代理店签约动销数据标题
将第一行单元格属性中样式修改为预定义样式,然后设置单元格居中、字体大小以及字体加粗
双击B3单元格,统计九大品牌代理店的签约门店总数
双击C3单元格,统计九大品牌代理店的签约动销总数
将第一行和第二行设置重复与冻结
添加控件参数
添加文本控件,控件值修改为年月:
添加下拉复选框控件,控件名称修改为month,数据字典中类型设置选择数据查询,数据集选择ds2,实际值和显示值选择month列
添加查询按钮组件
取消勾选para组件中 点击查询前不显示报表内容
保存报表,点击分页预览,查看报表显示效果
3.5.4.3 报表部署
参考需求一中操作
4 项目扩展
4.1 FineReport职业资格认证
FCA考试链接: https://cert.fanruan.com/
FCP-报表交付工程师报名链接: https://www.boxuegu.com/coursePage/?subject=fcp&pageType=0
4.2 FineBI工具学习
学习文档:https://help.fanruan.com/finebi/
学习视频:https://edu.fanruan.com/video?class1=2&class2=0
4.3 PowerBI工具学习
学习文档:https://learn.microsoft.com/zh-cn/power-bi/
学习视频:https://learn.microsoft.com/zh-cn/training/powerplatform/power-bi?WT.mc_id=powerbi_landingpage-marketing-page