iT邦幫忙

0

請教 PHP 直銷系統統計下線金額的寫法

php
-- 會員表單
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 的金額總和
不知道怎麼寫比較有效率

4
chiurick
iT邦新手 5 級 ‧ 2011-10-21 15:30:39
最佳解答

小弟我在很久很久很久以前寫作直銷獎金計算程式,分享一下:
如果不考慮獎金計算邏輯,單純的想知道某個人下線業績的總和其實可以這樣做

  1. 直銷上下線其實就是一棵樹

  2. 每個節點一定可以找到一個父節點

  3. 把每個父節點串起來就是絕對路徑

  4. 假設 A5的父節點為A4,A4的父節點為A3,A3的父節點為A2 ,以此類推 最終為root

  5. 建立樹狀目錄儲存:節點、父節點、絕對路徑。
    以A5為例既為 A5、A4、root\A\A1\A2\A3\A4\A5

  6. 所以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\......

  7. 當要查詢A5下面所有的節點時只要利用一個指令
    select 節點 from 樹狀目錄 where 絕對路徑 like 'root\A\A1\A2\A3\A4\A5%'
    A5 所有的節點都會跑出來

  8. 同理查詢A5下面所有的節點的業績
    select sum(節點業績) from 樹狀目錄 where 絕對路徑 like 'root\A\A1\A2\A3\A4\A5%'

後記:

  1. 用程式跑會迴圈或者遞迴都會需要一些時間。
  2. 為 絕對路徑 建立index 因為使用post like 所以在執行效能上又可以增進。
  3. 為每個節點建立絕對路徑是需要時間,僅須全面性做一次。
    3.1 未來如果是新節點建立,迴圈只要跑上線代樹,執行速度上應可接受
    3.2 如果是節點刪除、或者更換上線,都只是絕對目錄的update。
    可用sql 命令字串擷取的方式處理。速度也很快。

以上提供參考

4
doesjudas
iT邦新手 2 級 ‧ 2011-10-20 09:49:42

我會用最笨的寫法
A
+--B--D...
|
+--C--E...
:

*** 重點要避免無限迴圈狀況 ***

4
lukeshei
iT邦新手 3 級 ‧ 2011-10-21 09:15:05

用檔案系統的 目錄+檔案 做 最簡單, 這個應該是樹狀結構

6
chiounan
iT邦研究生 1 級 ‧ 2011-10-21 10:31:08

因為下線可以無限擴展,所以適合採用動態的資料結構像是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。

2
Albert
iT邦高手 1 級 ‧ 2011-10-22 16:33:45

這是 無限展階 程式

只要用 Stored Procedure 就可以輕易達成

在這分工合作的時代
不要都是一人獨撐
浪費 30天 為了省下 3萬!!!

看更多先前的回應...收起先前的回應...
chan15 iT邦新手 5 級 ‧ 2011-10-22 17:15:11 檢舉

謝謝 albertachen 的建議,我目前 sp 還不熟,但我會去嘗試看看

Albert iT邦高手 1 級 ‧ 2011-10-24 23:23:34 檢舉

請問大大是 [承包專案]
還是 [自我練習]
?

ticky520 iT邦新手 5 級 ‧ 2011-10-31 22:22:30 檢舉

我有寫過!當然是用遞迥....

c38dgigi iT邦新手 5 級 ‧ 2011-12-24 07:52:37 檢舉

這個我要買請問誰有現成套裝的不必重寫真(因預算算不高)請通知一下順便報價及功能說明謝謝

我要發表回答

立即登入回答