2012-06-10 74 views
1

我有4個疑問,我需要以建議的項目根據項目的用戶excecute他們已經表達了興趣:MySQL的連接查詢 - 連接表到自己很多次

選擇5個隨機物品的用戶已經喜歡

SELECT item_id 
FROM user_items 
WHERE user_id = :user_person 
ORDER BY RAND() 
LIMIT 5 

選擇50人誰喜歡同樣的項目

SELECT user_id 
FROM user_items 
WHERE user_id != :user_person 
AND item_id = :selected_item_list 
LIMIT 50 

選擇原來的用戶喜歡

01的所有項目
SELECT item_id 
FROM user_items 
WHERE user_id = :user_person 

選擇5個項目,用戶已經不喜歡向用戶建議

SELECT item_id 
FROM user_items 
WHERE user_id = :user_id_list 
AND item_id != :item_id_list 
LIMIT 5 

我想知道的是我會怎麼excecute這是一個查詢什麼?

有幾個原因,我想這樣做:

  1. 的那一刻,我不得不excecute「選擇50人」查詢5次,並挑選前50名的人從中
  2. 然後,我必須執行'select 5 items'查詢50 *(初始用戶喜歡的項目數量)

一旦查詢被執行,我打算將查詢結果存儲在cookie中(如果用戶給出同意我使用cookies,否則他們根本沒有得到'物品建議')關鍵是查詢的散列,意味着它每天只會觸發一次/每週一次(這就是爲什麼我返回5條建議並隨機選擇一個鍵來顯示)

基本上,如果有人知道如何寫這些查詢作爲一個查詢,你能告訴我並解釋查詢中發生了什麼嗎?

回答

2

這將選擇你需要的所有物品:

SELECT DISTINCT ui_items.item_id 
FROM user_items AS ui_own 
JOIN user_items AS ui_others ON ui_own.item_id = ui_others.item_id 
JOIN user_items AS ui_items ON ui_others.user_id = ui_items.user_id 
WHERE ui_own.user_id = :user_person 
    AND ui_others.user_id <> :user_person 
    AND ui_items.item_id <> ui_own.item_id 

(請檢查結果是完全一樣的跟你的版本 - 我測試了它在一個非常小的假數據集)

接下來你只需這個緩存列表,並顯示5項隨機,因爲ORDER BY RAND()是非常低效的(非確定性查詢=>無緩存)

編輯:添加了DISTINCT不顯示重複行。

GROUP BY ui_items.item_id 
ORDER BY COUNT(*) DESC 
LIMIT 20 

要查詢的結束,將返回20個最:

您可以按降序普及爲了去除DISTINCT並添加以下代碼來查詢的結束也返回一個最流行的建議流行項目。

+0

另外,我認爲你的問題可以通過[Redis](http://redis.io/)作爲緩存數據庫有效解決,因爲你正在處理集合和隨機建議。如果你感興趣,請閱讀[The Little Redis Book](http://openmymind.net/2012/1/23/The-Little-Redis-Book/)(它是免費的) – scriptin

+0

你唯一缺少的是'GROUP BY ui_items。item_id ORDER BY COUNT(*)DESC LIMIT 20'其中,我測試了一個10,000對(從500個用戶和5000個項目中隨機選取)的虛擬桌子,這意味着項目不會出現多次! –

+0

只是爲了防止重複,我會使用'SELECT DISTINCT ui_items.item_id ...'。您的版本做的更多:它按受歡迎程度排序項目。在這種情況下,最好指定一個確切的子集進行排序:'ORDER BY COUNT(ui_items。*)DESC' - 只是爲了澄清代碼。 – scriptin