2011-08-10 34 views
1

嘗試過幾種可能性我已經停下來了。如果不超載數百查詢的MySQL服務器,這就是我想實現:在單個表上的MySQL複雜查詢問題

下面是表

CREATE TABLE `users` (
    `id` int(11) NOT NULL auto_increment, 
    `firstname` varchar(64) NOT NULL, 
    `lastname` varchar(64) NOT NULL, 
    `email` varchar(64) NOT NULL, 
    `status` smallint(5) NOT NULL, 
    `refchid1` int(11) NOT NULL, 
    `refchid2` int(11) NOT NULL, 
    `refchid3` int(11) NOT NULL, 
    `refchid4` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; 

說明:

  1. 我試圖調整一個人的地位基於一棵複雜的樹。每個用戶都有一個id,如auto_increment id字段所示。
  2. 用戶A將他的詳細信息輸入到表格中。
  3. 用戶B由用戶A refered,所以,當他的細節被輸入refchid1具有相同的ID作爲用戶A.
  4. 用戶C是由用戶B refered,他refchid1變成用戶B的ID和他的refchid2成爲用戶A的ID
  5. 用戶d由用戶C refered,他refchid1成爲用戶C的是,refchid2該用戶B和refchid3用戶A.

,如果你理解了上面的引用,你在正確的軌道上。

上述說明的樣本數據:

(6, 'Lars', 'Luna', '[email protected]', 25, 0, 0, 0, 0), 
(7, 'Sonya', 'Cox', '[email protected]', 25, 6, 0, 0, 0), 
(8, 'Aiko', 'Hodge', '[email protected]', 25, 7, 6, 0, 0), 
(9, 'Lillith', 'Bray', '[email protected]', 25, 8, 7, 6, 0), 
(10, 'Macey', 'Hayes', '[email protected]', 25, 9, 8, 7, 6); 

我試圖做到的是:

  1. 默認狀態是25(25,28,30,35,40)查看這基本上就是一種折扣系統,在這種系統中,您提及的人越多,他們引用的人越多,您在哪裏可以獲得更大的折扣。
  2. 如果用戶A至少有10個唯一用戶,他引用爲refchid1,他獲得狀態。
  3. 如果用戶A在refchid1中至少有10個uniuque用戶,而每個用戶在refchid1中有10個唯一用戶,其中用戶A是refchid2,則他獲得狀態。
  4. 用戶A在rechid1中有10個唯一用戶,每個用戶在refchid1中有10個唯一用戶,其中用戶A是rechid2,而用戶A在refchid3的refchid1中又有10個唯一用戶。

如前所述,測試的結構複雜,我想這樣做沒有數以百萬計的查詢超載MySQL服務器。查詢應該是一個UPDATE查詢,它將調整所有匹配用戶的狀態。

有沒有人有我如何完成這個解決方案?

+0

所以這種思維爲一棵樹基本上就意味着每10個用戶在任何級別提到更高水平的所有用戶獲得1個狀態點? – nobody

+0

這是一個正確的假設。 說明: 用戶A在refchid1上有10個引用,在refchid1上的這10個引用中,他們每個在refchid2上都有用戶A,他們在refchid1引用了10個用戶。 –

回答

0

我應該已經創建的用戶列表,並引用一個單獨的表,

CREATE TABLE reference 
(
    reference_id SERIAL, 
    new_user_id BIGINT UNSIGNED NOT NULL, 
    refered_user_id BIGINT UNSIGNED NOT NULL, 
    reference_depth INT UNSIGNED NOT NULL 
); 

,當你添加新的用戶,如果用戶被其他用戶refered,添加一行白衣深度1,

INSERT INTO reference SET 
    new_user_id = $new_user_id, 
    refered_user_id = $refered_user_id, 
    reference_depth = 1 

然後選擇鏈接到該用戶的所有引用,並增加深度絲毫1:

INSERT INTO reference (new_user_id, refered_user_id, reference_depth) 
SELECT $new_user_id, refered_user_id, reference_depth +1 
FROM reference WHERE new_user_id = $refered_user_id; 

,然後計算點

SELECT 
    SUM(
    IF(reference_depth = 1, 10, 0) 
    + IF(reference_depth = 2, 3, 0) 
    + IF(reference_depth = 3, 2, 0) 
    + IF(reference_depth > 3, 1, 0) 
) 
FROM reference 
WHERE new_user_id = $user_id 
+0

我會試一試,並報告給你。謝謝。 –

+0

您提供的代碼是構建一個Closure Table模型。計算點的部分不會像描述的那樣工作,但是如果我使用這個模型並設置SELECT SUM IF(reference_depth = 1,1,0),那麼我得到多少個level1查閱者的結果,其中查找等級2- 4,這正是我想要的。已經閱讀了Bill Karwin的Closure Tables,並將改變我的項目來改爲使用該模型。感謝您的建議並指引我朝着正確的方向發展。 –

0

您是否想到triggers? 由於您直接在表的行上更新狀態,而不是通過視圖動態生成它(我更喜歡),我認爲觸發插入操作然後創建適當的「if」語句可能是一個好主意。

否則,我會建議不使用狀態refchid *列,但只有一個REFID它指的是「父」 ID,然後使用視圖生成狀態值(關於recursivelly的REFID )。

+0

使用我收到的兩個答案,我認爲可能有辦法做到這一點。你會建議這是更新插入狀態的最佳方法嗎? [代碼] CREATE TRIGGER ins_trig BEFORE INSERT ON card_holders FOR EACH ROW BEGIN UPDATE用戶,(SELECT SUM(refchid1)AS總FROM card_holders WHERE refchid1 = 3)AS總 SET狀態= CASE WHEN狀態=「25 「THEN status =」28「 WHEN status =」28「THEN status =」30「 WHEN status =」30「THEN status =」35「 WHEN status =」35「THEN status =」40「 WHERE total> = 10 END; [/ code] –

1

我真的不知道如何計算積分,但是這個查詢可能會爲您提供足夠的數據來處理它,並在您使用公式時將其重寫爲更新查詢。

SELECT 
parent.*, 
SUM(IF(parent.id = child.refchid1, 1, 0)) AS count_ref1, 
SUM(IF(parent.id = child.refchid2, 1, 0)) AS count_ref2, 
SUM(IF(parent.id = child.refchid3, 1, 0)) AS count_ref3, 
SUM(IF(parent.id = child.refchid4, 1, 0)) AS count_ref4, 
COUNT(child.id) as count_ref 
FROM users AS parent 
LEFT JOIN users AS child 
    ON ( parent.id = child.refchid1 
     OR parent.id = child.refchid2 
     OR parent.id = child.refchid3 
     OR parent.id = child.refchid4) 
GROUP BY parent.id 
+0

我之前有過類似的查詢。我在數據庫中填入了4萬個條目,仔細設置了層次結構,以便來自1至116的幾個用戶會引用其他所有人。 使用上面的查詢,當我寫這個時,mysql服務器仍然試圖給我一個結果。運行5分鐘。返回結果的時間太長:) –

+0

我離開了你建議的運行45分鐘的查詢,仍然沒有結果:P –

+0

你在桌上有什麼鍵/索引?上述查詢的描述是什麼意思,是否使用密鑰? –