2011-07-05 87 views
1

我有類似的朋友表的東西。它叫contacts。它具有:聯繫表問題

  • user_id是用戶這是像接觸的所有者ID,
  • contact_id是該用戶那是在朋友user_id ID;

還有第二個表events。它有:

  • user_id是該事件的創建者的用戶的ID。

我需要選擇我的朋友創建的事件。所以如果我的聯繫人列表中有約翰和安娜,我需要顯示他們的事件。

這裏是解決方案:

SELECT `bio_community_events`.`id`, 
     `bio_community_events`.`begin_on`, 
     `bio_community_events`.`name` 
    FROM `bio_community_events` 
    JOIN `bio_contacts` ON (`bio_contacts`.`contact_id` = `bio_community_events`.`user_id`) 
WHERE `bio_contacts`.`user_id` = '33' 

即,我的ID是33。它給了我朋友們的活動。問題來了...

有些情況下,我不是與朋友進行聯繫的人。反之亦然,安娜做到了。這個查詢會簡單地忽略它,並且不顯示Anna的結果。

+0

你爲什麼要關注事件的創造者,而不是事件記錄器d本身? –

+0

像'SELECT ... FROM bio_contacts'? – daGrevis

回答

2
SELECT `bio_community_events`.`id`, 
     `bio_community_events`.`begin_on`, 
     `bio_community_events`.`name` 
    FROM `bio_community_events` 
    JOIN `bio_contacts` 
    ON (`bio_contacts`.`contact_id` = `bio_community_events`.`user_id`) 
WHERE `bio_contacts`.`user_id` = '33' 

UNION ALL         --- or UNION if this gives you 
              --- duplicate row 
SELECT `bio_community_events`.`id`, 
     `bio_community_events`.`begin_on`, 
     `bio_community_events`.`name` 
    FROM `bio_community_events` 
    JOIN `bio_contacts` 
    ON (`bio_contacts`.`user_id` = `bio_community_events`.`user_id`) 
WHERE `bio_contacts`.`contact_id` = '33' 

或像這樣:

SELECT `bio_community_events`.`id`, 
     `bio_community_events`.`begin_on`, 
     `bio_community_events`.`name` 
    FROM `bio_community_events` 
    JOIN 
    (SELECT `bio_contacts`.`contact_id` AS id 
     FROM `bio_contacts` 
     WHERE `bio_contacts`.`user_id` = '33' 
    UNION ALL        
     SELECT `bio_contacts`.`user_id` AS id 
     FROM `bio_contacts`         
     WHERE `bio_contacts`.`contact_id` = '33' 
    ) AS un 
    ON (un.id = `bio_community_events`.`user_id`) 

要以限制設置爲所有示例#1中返回的行使用:

(SELECT ...) 
UNION ALL 
(SELECT ...) 

ORDER BY ?  --- optional 
LIMIT x ; 

使用ORDER BY在這樣的查詢中可能會非常昂貴。你也可以有這樣的(不同的)查詢,可以使用索引:

(SELECT ... 
    ORDER BY ? 
    LIMIT a 
) 
UNION ALL 
(SELECT ... 
    ORDER BY ? 
    LIMIT b 
) 

LIMIT x ;   --- with or without this LIMIT 

另一種方式來解決原來的問題是使用EXISTS

SELECT `bio_community_events`.`id`, 
     `bio_community_events`.`begin_on`, 
     `bio_community_events`.`name` 
    FROM `bio_community_events` 
    WHERE EXISTS 
     (SELECT * 
      FROM `bio_contacts` 
     WHERE `bio_contacts`.`user_id` = '33' 
      AND `bio_contacts`.`contact_id` = `bio_community_events`.`user_id` 
    ) 
    OR EXISTS 
     (SELECT * 
      FROM `bio_contacts` 
     WHERE `bio_contacts`.`contact_id` = '33' 
      AND `bio_contacts`.`user_id` = `bio_community_events`.`user_id` 
    ) 

或:

SELECT `bio_community_events`.`id`, 
     `bio_community_events`.`begin_on`, 
     `bio_community_events`.`name` 
    FROM `bio_community_events` 
    WHERE EXISTS 
     (SELECT * 
      FROM `bio_contacts` 
     WHERE (`bio_contacts`.`user_id` = '33' 
      AND `bio_contacts`.`contact_id` = `bio_community_events`.`user_id`) 
      OR (`bio_contacts`.`contact_id` = '33' 
      AND `bio_contacts`.`user_id` = `bio_community_events`.`user_id`) 
    ) 

如果您的計劃是要fi找到最有效的查詢,嘗試所有正確工作(使用IN,使用UNION,使用EXISTS) - 添加您想要偏離的ORDER BY - 並檢查其速度和執行計劃。

我至少具有:

在表
  • bio_community_events
    • 上用於ORDER BY

字段(一個或多個)上user_id

  • 的索引的索引和

    • bio_contacts,兩個複合指標
      • (contact_id, user_id)
      • (user_id, contact_id)

    和POST另外一個問題,如果你不能讓它在小於X毫秒運行( X由你的老闆決定:)

  • +0

    如何在示例#1中爲所有返回的行設置限制? – daGrevis

    +0

    @daGrevis:查看最新的答案。 –

    +0

    有沒有更快*的方式?我的老闆告訴我這個查詢不好,因爲當有數百萬條記錄時......它會花費很多時間來執行。是這樣嗎? – daGrevis

    0

    你需要讓你的朋友的用戶ID,以及:

    SELECT `bio_community_events`.`id`, `bio_community_events`.`begin_on`, `bio_community_events`.`name` 
    FROM `bio_community_events` 
    JOIN `bio_contacts` 
        ON (`bio_contacts`.`contact_id` = `bio_community_events`.`user_id`) 
    WHERE `bio_contacts`.`user_id` = '33' 
    OR `bio_contacts`.`user_id` IN (SELECT `contact_id` FROM `contacts` WHERE `user_id` = 33) 
    
    +0

    [Err] 1052 - where子句中的列'user_id'不明確。 – daGrevis

    +0

    我修正了那個錯誤。在第二選擇錯誤的表名。無論如何,這個查詢給了我和以前相同的結果。 – daGrevis

    +0

    那麼,你說你的桌子被命名爲「聯繫人」,或者它是bio_contacts? – Candide

    1
    SELECT id, begin_on, name 
    FROM bio_community_events 
    WHERE user_id IN (SELECT user_id FROM bio_contacts WHERE contact_id = '33') 
    OR user_id IN (SELECT contact_id FROM bio_contacts WHERE user_id = '33') 
    
    +0

    這也給我我的事件。 – daGrevis

    +0

    你只想要你的朋友活動嗎?如果是這樣,我編輯了我的示例 –

    +0

    是的,我只想要我的朋友的事件。不是我自己。不是其他人。你編輯的例子行爲很奇怪。它返回相同的條目12次! – daGrevis