-- 會員表單
CREATE TABLE IF NOT EXISTS tbl_member (
m_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
m_name VARCHAR(100) COMMENT '會員姓名',
parent_id INT UNSIGNED DEFAULT 0 COMMENT '上線 ID'
) ENGINE=MYISAM COLLATE utf8_unicode_ci CHARACTER SET utf8;
-- a 為最大上線
-- b 以及 c 為 a 的下線
-- d 為 b 的下線
-- e 為 c 的下線
INSERT INTO tbl_member (m_name, parent_id) VALUES('a', 0);
INSERT INTO tbl_member (m_name, parent_id) VALUES('b', 1);
INSERT INTO tbl_member (m_name, parent_id) VALUES('c', 1);
INSERT INTO tbl_member (m_name, parent_id) VALUES('d', 2);
INSERT INTO tbl_member (m_name, parent_id) VALUES('e', 3);
-- 金額紀錄
CREATE TABLE IF NOT EXISTS tbl_sale (
s_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
m_id INT UNSIGNED DEFAULT 0 COMMENT '會員 ID',
s_money INT UNSIGNED DEFAULT 0 COMMENT '金額',
s_date DATETIME COMMENT '日期紀錄',
parent_id INT UNSIGNED DEFAULT 0 COMMENT '上線 ID'
) ENGINE=MYISAM COLLATE utf8_unicode_ci CHARACTER SET utf8;
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (2, 100, NOW(), 1);
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (2, 200, NOW(), 1);
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (3, 300, NOW(), 1);
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (3, 400, NOW(), 1);
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (4, 100, NOW(), 2);
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (4, 200, NOW(), 2);
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (5, 200, NOW(), 3);
INSERT INTO tbl_sale (m_id, s_money, s_date, parent_id) VALUES (5, 300, NOW(), 3);
下線無窮延伸的直銷系統
假設以 a 為第一層,應該要抓出 b、c、d、e 的金額總和
不知道怎麼寫比較有效率
小弟我在很久很久很久以前寫作直銷獎金計算程式,分享一下:
如果不考慮獎金計算邏輯,單純的想知道某個人下線業績的總和其實可以這樣做
直銷上下線其實就是一棵樹
每個節點一定可以找到一個父節點
把每個父節點串起來就是絕對路徑
假設 A5的父節點為A4,A4的父節點為A3,A3的父節點為A2 ,以此類推 最終為root
建立樹狀目錄儲存:節點、父節點、絕對路徑。
以A5為例既為 A5、A4、root\A\A1\A2\A3\A4\A5
所以A5多個下線 A6、A6-1、A6-2、A6-3..以及其下線的絕對目錄都會類似下面的結構
root\A\A1\A2\A3\A4\A5\A6
root\A\A1\A2\A3\A4\A5\A6-1 ......
root\A\A1\A2\A3\A4\A5\A6\......
當要查詢A5下面所有的節點時只要利用一個指令
select 節點 from 樹狀目錄 where 絕對路徑 like 'root\A\A1\A2\A3\A4\A5%'
A5 所有的節點都會跑出來
同理查詢A5下面所有的節點的業績
select sum(節點業績) from 樹狀目錄 where 絕對路徑 like 'root\A\A1\A2\A3\A4\A5%'
後記:
以上提供參考
我會用最笨的寫法
A
+--B--D...
|
+--C--E...
:
*** 重點要避免無限迴圈狀況 ***
因為下線可以無限擴展,所以適合採用動態的資料結構像是linked-list來建立網路(或通稱Graph)的資料結構。Graph的組成包含有Vertex與Edge,Vertex代表會員,而有方向性的Edge代表上下線關係,另外Vertex或是Edge上的Weight可以表示金額。
建構好代表直銷會員關係的Graph之後,就可以透過graph traversal的技巧來走訪Edge,並獲取金額的總和。例如要查詢會員C的金額,就從Vertex C出發,而唯一相通的Edge是Vertex E,這時加總的Weight就是C的金額。又例如要計算會員A的金額,就從Vertex A出發,Vertex A接連著Vertex B與C,所以就再去計算B與C的Weight,再加總起來獲得A的Weight。要實做這個traversal最直覺的是採用遞迴(recursive),用函數呼叫的方式反覆計算某個Vertex的Weight。就像是:
F(A)=F(B)+F(C)
F(B)=F(D)
F(C)=F(E)
F(E)=...
但是當你的會員關係變多變複雜之後(每個會員可能有多個下線),recursive就會顯得沒效率,所以我建議採用dynamic programming的作法。因為走過的Vertex的Weight都已得到,只要先記錄下來,就可以避免重複計算那些走過的Edge的Weight。
這是 無限展階 程式
只要用 Stored Procedure 就可以輕易達成
在這分工合作的時代
不要都是一人獨撐
浪費 30天 為了省下 3萬!!!