1. 程式人生 > >網頁端報表note:查詢結果拼接join以及setParameterList避坑寫法

網頁端報表note:查詢結果拼接join以及setParameterList避坑寫法

需求:
會員名稱 會員手機號 消費次數 跨店消費 最多消費門店 總消費額(元) 最近消費時間 註冊時間 註冊門店

資料庫表:
1 總店和分店的關係表,僅存放兩者的id
2 訂單表,門店code(唯一),消費金額,顧客id,建立日期
3 顧客表,顧客id,建立日期,電話(部分為空),姓名(部分為空),註冊門店,建立日期(注意存在同一個手機號碼對應多個顧客id,同一個手機號碼在不同門店開通了會員或系統未能實時同步會員資訊)
4 group表,門店code,門店名稱,門店所屬groupsId

分析:
最多消費門店 和 跨店消費 需要通過 同一顧客表的手機號碼在不同店鋪的消費總額和次數獲取

對於本人而言的難點:
1 分頁
2 日期區間
3 查詢條件 in

解決方式:
1 從訂單表order_info 通過建立日期和消費門店篩選出需要彙總的訂單

新手的寫法–

String sqlOrder = "select * from order_info a where a.status =1 and a.CUSTOMER_ID is not null and a.FLG_DELETED=0 "
                +" and a.CREATE_TIME >= ? and a.CREATE_TIME <= ? and a.BELONG_COMPANY_ID in
:belongCompanyId"; //佔位符和命名 同時使用,若只執行一次是OK的,但是我要用2次,無奈只能改成下面的樣子

踩坑後的寫法–

String sqlOrder = "select * from order_info a where a.status =1 and a.CUSTOMER_ID is not null and a.FLG_DELETED=0 "
                +" and a.CREATE_TIME >= :startDate and a.CREATE_TIME <= :endDate and a.BELONG_COMPANY_ID in
(:belongCompanyId) "; String sqlOrder1 = "select * from order_info a where a.status =1 and a.CUSTOMER_ID is not null and a.FLG_DELETED=0 " +" and a.CREATE_TIME >= :startDate1 and a.CREATE_TIME <= :endDate1 and a.BELONG_COMPANY_ID in (:belongCompanyId1) "; query.setParameter("startDate", startDate).setParameter("endDate",endDate).setParameter("startDate1", startDate).setParameter("endDate1",endDate).setParameterList("belongCompanyId", belongCompanyId).setParameterList("belongCompanyId1", belongCompanyId);

部分blog可能說setParameterList只能放在最後使用,其實,那只是在與佔位符同時使用的情況
若你只使用命名,則無位置限制

2 考慮到最大消費門店和總消費額是兩個維度的查詢結果, 聯查custom和sqlOrder的結果,分為兩條sql執行
2.1 統計單個會員在duo家店鋪的彙總銷售額
group by mobile_phone
2.2 單個會員在單家店鋪的彙總銷售額
先 group by mobile_phone,門店code 再 group by mobile_phone
理論上,兩條sql的查詢結果數應該是一致,且能通過mobile_phone進行關聯
注意,這是就無法考慮mobile_phone為空的情況,在group by時mobile_phone為空的會被資料庫視為同一條資料,所以我聯查時會把custom表的mobile_phone為空的篩選,但是部分是空字串的篩選失敗

3 join 合併查詢結果,執行時間基本忽略不計,兩條sql分開查詢時各1.4s,join合併時2.8s,效率較高
注意:
1 union是縱向合併查詢結果的 ,即 1+1=2
2 或許有人提出 兩表通過where關聯查詢,查詢結果是700條時,執行時間是4s多
3 或許有人嘗試在dao層寫兩個方法,分別查詢,然後在java合併結果,這程式碼複雜,就別自己為難自己了

//合併資料的sql
//sqlCha sqlPer  就是  兩條sql
String sqlJoin = "select ta.CUSTOMER_ID,tb.NAME,ta.MOBILE_PHONE,tb.totalTimes,ta.chains,ta.company,tb.totalpays,tb.lastTime,tb.signTime,tb.signcomp "       
                + "from("+ sqlCha +") as ta JOIN ("+ sqlPer +") as tb on ta.MOBILE_PHONE=tb.MOBILE_PHONE ORDER BY totalpays desc";  

4 分頁setFirstResult和setMaxResults

//注意setFirstResult是從0開始
pagelet.setDatas(query.setFirstResult(10*(pageNo-1)).setMaxResults(pagelet.getPerPageSize()).list());

考慮到翻頁,所以要把查詢結果總數也返回到頁面
//select count 就不解釋了