2012-06-10 53 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