除了excel,一般公司用什么報表工具
目前,國內市場第一的報表工具應該是FineReport,開源的有Birt、JasperReports。
金蝶用友廣泛用于財務,BO是SAP的BI工具,水晶報表是SAP的報表工具。
以上都是商業工具,好處是一方面報表工具是一個數據庫程序,企業級的系統工具,對于讀取連通數據庫、集成開發會更加靈活;另一方面諸多報表廠商由于需要實現商業化,在產品的打磨和服務上下足了功夫,很多工具在實際的業務場景中遠比excel方便。
關于FineReport:日常工作中,涉及到表格、圖表、分析、數據處理,大家首選的一定是Excel。但很多人困惑于Excel的深入學習難度,雞肋的大數據處理效率。
比如某網友為處理七八個維度,近萬條數據奔潰不已;又有人幾十萬行的數據把電腦頻頻跑崩;再者,隨著多任務線之間的交叉,匯總任務呈幾何級數增加……
倒不是說Excel完成不了這類任務,Excel作為個人辦公軟件絕無僅有,但作商業用,效率還稍有不足。最主要的原因還是處理速度上,excel更多時候充當的是輕量數據庫和計算功能。
懂IT的朋友可能會說,交給數據庫啊,寫兩條SQL就解決了。再不行,找程序員寫代碼,什么圖形化的界面,分析,圖表,數據錄入,修改刪除界面,都可以交由程序開發,性能杠杠的。那如果有一款工具能解決掉數據庫之后的數據增改刪,展現,交互分析,移動大屏展示,并做到辦公協同,那就是小編今天想來講講的FineReport了。
FineReport的本質是一個通用的報表制作和數據可視化工具,是一個開放的商業報表工具。好比Excel,小到可以存儲統計數據、制作各式各樣的圖表、dashboard,大到制作財務報表、開發進銷存系統。
下文將從技術的角度講講FineReport,操作上為何能省時省人力,如何在實現系統化數據分析的同時又能有驚艷的可視化。
一、如何花1小時完成一張復雜報表,解放10+人力?1、關于FineReport的制表原理
FineReport是通過連接數據庫,讀取數據字段來設計報表模板的,所以在制作模板前先要知道數據庫的類型、地址、訪問數據庫的用戶名密碼,兩者建立一個數據連接后才可開始設計模板。然后依據所需功能(表格展示?填報?dashboard分析?)和表樣來操作模板,最后在web端展示。
制作模板時處理的對象是數據字段(區別于Excel的單元格數據),模板中一個單元格放一個數據字段,web端展示時字段擴展。FineReport報表中單元格的擴展是有方向的,可縱向擴展,也可橫向擴展,也可以不擴展。
單元格的擴展是針對某一個單元格,當報表主體中綁定了多個單元格時,單元格與單元格之間依靠父子格關系跟隨擴展。子格的數據會根據父格的數據進行過濾分組顯示,并且還會跟隨父格的擴展方向而擴展。
2、三大類報表設計方式,解決日常所有報表需求,并且一表復用。
1)普通模板設計,此者最常用。依靠著單元格的擴展與父子格的關系來實現模板效果,可進行參數查詢,填報報表,圖表設計等。比如交叉報表、行式報表、分組報表等等。
2)聚合報表設計,針對不規則大報表。適用于一張模板中顯示多個獨立模塊的報表,幾個報表塊匯總在一起的復雜報表。
3)決策報表設計,就是表單,也是dashboard,用于彌補普通報表分頁預覽不能展示控件的問題。同時表單可以進行自由拖拽設計,自適應頁面大小顯示,自由制作駕駛艙可以更好的在各種大小類型的屏幕上展示,包括移動端、大屏。
以下舉例一些常見的報表格式。
交叉表
行式報表
分組報表
自由報表
3、參數實現數據查詢和過濾
在很多情況下,我們需要根據條件查詢數據,過濾。在FineReport中,通過設置參數綁定數據字段和過濾的控件(單選框復選框等等),參數可用JS編輯更多復雜的情況,通過界面輸入查詢條件來控制報表顯示的內容及形式,而后導出打印。
4、填報
填報就是向數據庫中錄入數據,用于固定格式固定條件的數據收集。就好比你注冊知乎時提交的郵箱、收集、用戶名、密碼,都會按照格式存放到數據庫中。
填報也需要一個模板,操作流程如下:
填報模板由控件組成,文本控件、數字控件、密碼控件、單復選框、網頁、文件等等??丶鴶祿侄?。有了填報,就可以收集數據,并且允許用戶實現對數據庫的增刪改。出于數據質量和數據安全的考慮,還可以對填報進入的數據做校驗操作。
5、打印&導入導出
FineReport的打印方式分為客戶端打印和服務器端打印。
服務器端打印就是使用報表應用所在的服務器,連接的打印機進行打?。?/p>
客戶端打印就是使用本地連接的打印機進行打??;又分為Flash打印、PDF打印、Applet打印以及本地打印。
出于對Excel的支持,有各種方式(如下)導出成Excel文件,同時,設計器中可導入Excel,填報也可直接導入帶有數據的Excel表樣。
二、如何制作酷炫的Dashboard可視化酷炫的dashboard都需要通過FineReport的表單(決策報表)來設計展現。通過拖拽報表塊、圖表塊和各類控件初步設計界面。
不同于普通報表,普通報表是一個整體,無法實現局部刷新。表單是由各個組件組成,可以實現組件內刷新,即局部刷新。像動態大屏都是全局或者局部刷新的,所以需要用決策報表制作實現。
1、決策報表制作過程
新建表單:FineReport支持新建工作薄,即普通報表模板,還支持新建表單,兩種設計模式;
拖入組件:FineReport表單支持多種不同的組件類型,包括報表塊、tab塊、絕對畫布塊、參數、圖表和控件等等;
定義數據集:定義各個組件數據來源,圖表組件數據即可來源于數據集,也可來源于單元格;
設置表單樣式:即設置表單的顯示樣式。
2、數據可視化與交互
很多網友以前給我留言,問這樣的可視化是什么圖表制作的。其實大多由FineReport自帶的H5圖表。此前有提到FineReport良好的開放性,可讓IT同事寫代碼開發,所以在制作時,也可接入Echarts等第三方控件來制作圖表。
3、實用而強大的數據地圖
finereport有很強大的地圖功能:基本地圖、GIS地圖、熱力地圖、大數據流向地圖等。
GIS地圖基于GIS地圖層進行數據展示,支持自定義GIS主題風格,能夠與數據表鉆取聯動。比如省級鉆取到市級、縣級、街道。
三、總結以上便是FineReport一部分功能,篇幅有限,很多細節無法展開。
要說效率,最大的好處就是從數據庫中讀出數據自動產生報表,且一類報表做成一個固定樣式的模板,每次只要同步一下,自動生產周期性的報表,如日報、周報、月報、季報等。每次按照條件查詢,Excel批量導出/打印,少了人力去一個一個用Excel統計匯總。
而且操作上,大多數功能FineReport都封裝成模塊了,包括寫SQL取數,匯總篩選過濾等,基本上都有對應的功能鍵。像著名的資產負債表,如果按照以往寫代碼或者寫復雜的SQL語句,就有點摧殘生命了,而且那天書般的SQL語句要是出點錯誰來查,如果數據來自多個源,那就徹底無法解脫了。
其次,在數據處理速度上,由于性能一部分依靠數據庫,一部分依靠FineReport的行式報表引擎,相比于Excel的單機效率,幾十萬行的數據秒出。再者,企業數據庫有各種自帶或第三方的集群方案,通過堆機器就可以近似于無限的加大數據儲存能力。
最后,FineReport除了解放個人,最大的貢獻應該是對企業。在商業用途上,我們要考慮效率,人員的培訓成本,協同性,還要考慮對企業業務的支撐、貢獻,這幾點Excel是比較難發揮貢獻的。有知友說“Excel用得再溜,老板也不會給你漲工資,可能還革了其他同事的命”。那是因為Excel處理了數據,但沒有得到有效結果去服務于業務帶來效益。那如果在報表之后,基于業務基于指標去做特定主題的數據分析,站在公司角度做數據化管理,為領導的業務決策提供有效意見,這樣的高度就別有不同了。
oracle與db2有哪些區別
Oracle和DB2的區別如下:
1、取前N條記錄Oracle:Select*fromTableNamewhererownum則在DB2下,此字段必須定義為timestamp,而不能定義成DATE,不然會報出字符串右截斷的錯誤對于DB2來說,在查詢條件中可以直接用字符串指定日期或時間戳類型字段的值,例如wherecreate_date='2007-04-26'、wherecreate_timestamp='2007-04-2608:08:08',無須使用字符串轉日期函數6、分頁的處理如果采用JDBC分頁的話,注意rownum在DB2中不受支持,比如從masa_area表中取得area_id最小的10條記錄,語句分別如下,注意這里的別名t書寫方法ORACLE:selectt.*from(selectrownumasr1,masa_area.*frommasa_areaorderbyarea_id)twheret.r1
oracle分頁查詢中計算總頁數的count(*) 效
看情況,如果你的SQL是個復雜SQL,如果能手工優化,那就動手寫個count的SQL,如果不能,要寫解析優化程序,將select后面帶的參數全部去掉改成*,其中要判斷diatinct的列外,另外末尾的orderby也去掉。這樣的話能提高點性能
my batis怎樣,實現mysql動態,分頁
在這些控件里要達到分頁的效果,一般都會傳2個參數,第一個是表示當前頁的索引(一般從0開始),第二個表示當前頁展示多少條業務記錄,然后將相應的參數傳遞給List<T>getList(PagenateArgsargs)方法,最終實現數據庫中的分頁時候可以使用limit關鍵詞(針對mysql)進行分頁,如果是oracle或者sqlserver他們都有自帶的rownum函數可以使用。
針對上述思路,首先在demo.mybatis.model下面新建一個名為PagenateArgs的分頁參數實體類與一個名為SortDirectionEnum的枚舉類,里面包含當前頁面索引pageIndex,當前頁展示業務記錄數pageSize,pageStart屬性表示從第幾條開始,(pageStart=pageIndex*pageSize)因為limit關鍵詞用法是表示【limit起始條數(不包含),取幾條】,orderFieldStr排序字段,orderDirectionStr排序方向,所以具體創建如下:
packagedavid.mybatis.model;/**分頁參數實體類*/publicclassPagenateArgs{privateintpageIndex;privateintpageSize;privateintpageStart;privateStringorderFieldStr;privateStringorderDirectionStr;publicPagenateArgs(){//TODOAuto-generatedconstructorstub}publicPagenateArgs(intpageIndex,intpageSize,StringorderFieldStr,StringorderDirectionStr){this.pageIndex=pageIndex;this.pageSize=pageSize;this.orderFieldStr=orderFieldStr;this.orderDirectionStr=orderDirectionStr;pageStart=pageIndex*pageSize;}publicintgetPageIndex(){returnpageIndex;}publicintgetPageStart(){returnpageStart;}publicintgetPageSize(){returnpageSize;}publicStringorderFieldStr(){returnorderFieldStr;}publicStringgetOrderDirectionStr(){returnorderDirectionStr;}}
packagedavid.mybatis.model;/**排序枚舉*/publicenumSortDirectionEnum{/**升序*/ASC,/**降序*/DESC}
完成上面的步驟以后在IVisitorOperation接口類中繼續添加一個方法publicList<Visitor>getListByPagenate(PagenateArgsargs),這次的分頁其實也就是在這個的基礎上稍加改動即可,IVisitorOperation接口類改動后如下所示:
packagedavid.mybatis.demo;importjava.util.List;importdavid.mybatis.model.PagenateArgs;importdavid.mybatis.model.Visitor;importdavid.mybatis.model.VisitorWithRn;publicinterfaceIVisitorOperation{/**基礎查詢*/publicVisitorbasicQuery(intid);/**添加訪問者*/publicintadd(Visitorvisitor);/**刪除訪問者*/publicintdelete(intid);/**更新訪問者*/publicintupdate(Visitorvisitor);/**查詢訪問者*/publicVisitorquery(intid);/**查詢List*/publicList<Visitor>getList();/**分頁查詢List*/publicList<Visitor>getListByPagenate(PagenateArgsargs);}
接下來改動VisitorMapper.xml配置文件了,新增一個<select>節點id與參數類型參照前幾章的方式配置好,如下此處新增的id就為getListByPagenate,配置好以后如下
<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""
http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="david.mybatis.demo.IVisitorOperation"><!--useGeneratedKeys="true"代表是否使用自增長序列,keyProperty="Id"指定自增長列是哪一列,parameterType="Visitor"指定IVisitorOperation接口類中定義中所傳的相應類型--><insertid="add"parameterType="Visitor"useGeneratedKeys="true"keyProperty="Id">insertintoVisitor(Name,Email,Status,CreateTime)values(#{name},#{email},#{status},#{createTime})</insert><deleteid="delete"parameterType="int">deletefromVisitorwherestatus>0andid=#{id}</delete><updateid="update"parameterType="Visitor">updateVisitorsetName=#{name},Email=#{email},Status=#{status}whereid=#{id}andStatus>0;</update><selectid="query"parameterType="int"resultType="Visitor">selectId,Name,Email,Status,CreateTimefromvisitorwhereid=#{id}andStatus>0orderbyId</select><selectid="basicQuery"parameterType="int"resultType="Visitor">select*fromvisitorwhereid=#{id}andStatus>0orderbyId</select><selectid="getList"resultMap="visitorRs"><includerefid="getListSql"/></select><sqlid="getListSql">select*fromVisitorwherestatus>0</sql><!--以下為新增部分用來分頁,orderBySql這個提取出來是為了后面有示例復用--><resultMaptype="Visitor"id="visitorRs"><idcolumn="Id"property="id"/><resultcolumn="Name"property="name"/><resultcolumn="Email"property="email"/><resultcolumn="Status"property="status"/><resultcolumn="CreateTime"property="createTime"/></resultMap><selectid="getListByPagenate"parameterType="PagenateArgs"resultType="Visitor">select*from(<includerefid="getListSql"/><includerefid="orderBySql"/>)t<!--#{}表示參數化輸出,${}表示直接輸出不進行任何轉義操作,自己進行轉移--><iftest="pageStart>-1andpageSize>-1">limit#{pageStart},#{pageSize}</if></select><sqlid="orderBySql">orderby${orderFieldStr}${orderDirectionStr}</sql></mapper>這里面的字段屬性都是針對PagenateArgs參數類中的屬性名,保持一致。
<iftest="pageStart>-1andpageSize>-1">limit#{pageStart},#{pageSize}</if>
在DemoRun類中創建測試方法:
/**分頁參數*/publicstaticvoidqueryVisitorListWithPagenate(intpageIndex,intpageSize,StringorderField,StringorderDire){PagenateArgsargs=newPagenateArgs(pageIndex,pageSize,orderField,orderDire);SqlSessionsession=MybatisUtils.getSqlSession();IVisitorOperationvOperation=session.getMapper(IVisitorOperation.class);List<Visitor>visitors=vOperation.getListByPagenate(args);for(Visitorvisitor:visitors){System.out.println(visitor);}MybatisUtils.closeSession(session);MybatisUtils.showMessages(CRUD_Enum.List,visitors.size());}
DemoRun.queryVisitorListWithPagenate(0,100,"id",SortDirectionEnum.DESC.toString());
運行后下測試結果,先按Id倒序排列,查的Visitor表一共有14條記錄,
假設取在第2頁取5條,執行下面也就是6-10條數據,這樣傳參數就行了
DemoRun.queryVisitorListWithPagenate(1,5,"id",SortDirectionEnum.DESC.toString());
結果如下:
實現了一個分頁邏輯.
Oracle與Mysql主鍵、索引及分頁的區別小結
非葉子節點也是存儲三列,不過是先按照第一字段排序,相同按第二字段排序,依次類推
mysql(innodb)是索引組織表,葉子節點是存的表的主鍵
關于oracle抽取數據的問題
工具太多了?。耗愕男枨笫且淮涡赃€是多次的?1.如果一次性的,用oracle本身的數據導出的速度非常快exp導出數據,然后同步到目的端,然后才導入2.如果是多次的,你對及時性要求如何,如果要求比較高,可采用CDC的實時抽取,詳細方案可參見我寫的文章,里面有具體的步驟和效果如果實時性要求不高,方案可采用傳統的etl工具,如kettle等,我的文章里面也有詳細的介紹希望可以幫到你