微信三級分銷程式關於會員關係的設計
最近幾年微信公眾號三級分銷程式挺火的,關於微信的程式開發,功能點比較多,如訊息推送、自定義選單,jssdk整合,支付介面等等,這些都可以到官方查閱文件:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN,本文主要討論一下會員三級關係的資料庫設計。從優化角度來重新設計。
首先看一下傳統的表設計:
以下是一張會員資訊表,這裡WxId是微信公眾號的id(因我設計的這個程式是要支援多個微信公眾號的),UserId是當前會員id,下圖中的Pid就是會員的上一級使用者id
下面看一下資料:
根據上圖,userid=1的這個會員Pid為0的說明會員是頂級的,沒有任何人推廣。userid=2的這個會員pid為1,說明他是userid為1的會員推廣而來。然後看userid=7的這個會員,他的pid=2,說明他是userid=2的這個會員推廣來。說白了推廣關係就是:
userid(1)->userid(2)->userid(7)
userid(1)->userid(3)
userid(1)->userid(4)
userid(1)->userid(5)
userid(1)->userid(6)
那麼我們要查詢一個會員(假設他的id為1)所有的推廣一級會員,對應的sql就是:select * from t_user where Pid=1,這裡沒有什麼問題,到是不難
那繼續來,要查詢他的二級或是三級分銷會員的話,就麻煩了,需要使用子迴圈了。對應的程式碼如下:
public String gets(int pid){
StringBuffer sb=new StringBuffer(sb);
ArrayList list=(ArrayList)DaoFactory.getUserDAO().exe("select id,Pid from t_user where Pid="+pid);
for (Iterator iter = list.iterator(); iter.hasNext(); ) {
DataField df=(DataField)iter.next();
sb.append("<li>"+df.getInt("id")+"</li>");
//遞迴呼叫
sb.append(gets(df.getInt("id")));
}
}
上面看到了,主要解決辦法就是遞迴呼叫。雖然功能也能實現,但在數量比較大的情況下,很容易產生效能問題(這裡只是查詢會員,如果在統計每個級別下會員的消費,收入統計時,需要和消費表關係查詢,那效能不知卡到什麼時候)。
下面重點來了,我們重新設計一下表,這裡我們主要是通過資料庫設計來解決,我們知道資料庫儲存數量量不怕多,於是我們想,可以這樣,每當使用者推廣一個會員的時候,我們向一個表(暫且叫作使用者關係表)寫入他的級別關係不就行了嗎。比如 a推廣了b,然後b推廣了c,c推廣了d,這樣我我們就向資料庫中寫一個記錄b以上三級的關係。
看一下表中的資料
上圖中,除了原來的會員表,我們新增加了個會員關係表:t_user_relations
這裡看到,ChildId=2的這個會員,他是id為1(Pid=1)的一級分銷使用者(FxLevel=1)
ChildId=7的這個會員,資料庫中有兩條記錄,一個是:他是id為2(Pid=2)的一級分銷使用者(FxLevel=1),再就是他是id為1(Pid=1)的二級分銷使用者(FxLevel=2),所以不難理解,如果一個會員上面有三級的話,這裡應該有三條記錄。簡單理解就是,當用戶新增加時,將此使用者上面所有級別對應的使用者資訊記錄到使用者關係表中。
這樣,當我們要查詢一個會員所有一級會員時,可以使用sql:select * from t_user_relations where Pid=1 and FxLevel=1
所有二級會員sql:select * from t_user_relations where Pid=1 and FxLevel=2
所有三級會員sql:select * from t_user_relations where Pid=1 and FxLevel=3
當我們需要統計三級會員的消費總額的時候,可以很方便使用sql:select sum(t_pay.Money) from t_user_relations,t_pay where t_user_relations.ChildId=t_pay.Userid and t_user_relations.Pid=1 and t_user_relations.FxLevel=3
同理查詢二級會員的消費:select sum(t_pay.Money) from t_user_relations,t_pay where t_user_relations.ChildId=t_pay.Userid and t_user_relations.Pid=1 and t_user_relations.FxLevel=2
那要查詢所有子會員的消費怎麼辦?總不能寫三個sql吧,當然不會了。使用條件FxLevel>0不就可以了嗎:)
select sum(t_pay.Money) from t_user_relations,t_pay where t_user_relations.ChildId=t_pay.Userid and t_user_relations.Pid=1 and t_user_relations.FxLevel>0
這樣一個sql就解決了。如果使用一開始使用的遞迴方法,隨著資料量的增長,速度會非常非常的糟糕。
上面你還可能 還會問一個問題,那如果知道某個會員他是誰的一級,誰的二級呢,.....?這需要用到第一個方法設計的表了,看到了,上面的表設計我們還是要用到:)
select Pid from t_user where id=2
if(Pid!=0)說明還不是頂級,繼續查。這裡可以 使用遞迴查詢或做三次查詢(通過 pid是否為0,這樣有的可能只是一級或兩次查詢,最多就是3次),放心,這樣的不會太影響效能的,可以忽略不計。
或者把id,pid資料放到快取裡,redis是個不錯的選擇。大家可以試下了。
最後看一下偶開發的效果:)