2013-04-23 112 views
2

我需要一个基于他所关注的电视节目,为用户查找推荐电视节目的查询。 做这个,我有以下表格:WHERE子句中的MySQL变量

  • 包含至极显示用户为以下,看到事件的百分比表Progress(解决这个问题,我们可以假设我只有一个用户数据库)

  • Suggested包含_id1_id2value(值是显示使用id = _id1并用ID的显示之间的连接的强度= _id2:越value是很大的,越在S如何有共同之处)。 请注意,在此表中适用交换属性,因此id1_id2之间的连接强度与_id1_id2相同。而且不会有两行如ROW1._id1 = ROW2._id2 AND ROW1._id2 = ROW2._id1

  • ShowCache包含有关电视节目的详细信息,如名字等。

下面的查询是什么,我试图做的,但结果是空集:

SET @a = 0; //In other tests this line seem to be necessary 
SELECT `ShowCache`.*, 
     (SUM(value) * (Progress.progress)) as priority 
FROM `Suggested`,`ShowCache`, Progress 
WHERE 

    ((_id2 = Progress.id AND _id1 NOT IN (SELECT id FROM Progress) AND @a:=_id1)//There is a best way to set a variable here? 

    OR 

    (_id1 = Progress.id AND _id2 NOT IN (SELECT id FROM Progress) AND @a:=_id2)) 

    AND `ShowCache`._id = @a //I think that the query fails here 

GROUP BY `ShowCache`._id 
ORDER BY priority DESC 
LIMIT 0,20 

我知道这个问题是有关变量的用法,但我解决不了的。任何帮助真的很感激。


PS:的主要问题是,(由于可交换礼),不变量,我需要两个查询,至极大约需要3秒开始执行(查询比上述更复杂)。我真的试图做一个单一的查询来完成这项任务

PPS:我也绑定了XOR操作,导致无限循环?!?!?这里的WHERE子句我想:

((_id2=Progress.id AND @a:=_id1) XOR (_id1=Progress.id AND @a:=_id2)) AND `ShowCache`._id = @a 

编辑: 我想出这个WHERE不使用任何变量条件:

(_id2 = Progress.id OR _id1 = Progress.id) 
AND `ShowCache`._id = IF(_id2 = Progress.id, _id1,_id2) 
AND `ShowCache`._id NOT IN (SELECT id FROM Progress) 

它的工作原理,但它是非常缓慢的。

+1

jquery和你的问题有什么关系? – razzak 2013-04-23 16:08:45

+0

Ops ...错误的标签,我的意思是查询 – Spotlight 2013-04-23 17:03:15

回答

1

您尝试使用xor很聪明。如果你想获得这种不匹配的值要使用按位异或这是^

Progress.id^^ _id1 _id2

3^2^3 = 2

2^2^3 = 3

您可以使用这种伎俩来设置一个连接,真正简化您的查询(消除OR的,而不是在的和做的一个查询,而不变量。)


select users.name as username, showcache.name as show_name, 
    sum(progress * value) as priority from users 
inner join progress on users.id = progress.user_id 
inner join suggested on progress.show_id in (suggested.id_1, suggested.id_2) 
inner join showcache on showcache.id = 
    (suggested.id_1^suggested.id_2^progress.show_id) 
where showcache.id not in 
    (select show_id from progress where user_id = users.id) 
group by showcache.id 
order by priority desc; 

我还设置一个小提琴进行论证: http://sqlfiddle.com/#!2/2dcd8/24

要打破它。我创建了一个用户表与单个用户(但该解决方案将与多个用户使用。)

的选择,并加入进步非常简单。在加盟建议采用作为替代使用OR

的加盟showcache是​​按位异或发生在那里写它。其中一个id链接到progress.show_id,我们想使用另一个。

它包括不排除从结果已经看过的节目。我可以改变它不存在?但是这样看起来更清楚。

+0

非常感谢!我必须问:在SELECT中使用'progress * SUM(value)作为优先级'而不是'progress * value'会更正确,还是我理解错误? – Spotlight 2013-04-23 21:14:30

+0

是的,我应该编辑答案。 – 2013-04-23 21:22:19

+0

再次感谢! PS:XOR操作非常巧妙。有一个等效的操作,3 x 3 x 2 = 3? X和? – Spotlight 2013-04-23 21:26:25

0

你设置@ a的值的两倍where子句中,这意味着该查询实际上熬煮至:

... 
WHERE ... AND `ShowCache`._id = _id2 

MySQL的演算值为在第一个遇到的顺序变量赋值,所以你应该离开@一个常量,直到子句的结束,然后分配一个新的值,例如。摹

mysql> set @a=5; 
mysql> select @a, @a+1, @a*5, @a := @a + 1, @a; 
+------+------+------+--------------+------+ 
| @a | @a+1 | @a*5 | @a := @a + 1 | @a | 
+------+------+------+--------------+------+ 
| 0 | 1 | 0 |   1 | 1 | 
| 1 | 2 | 5 |   2 | 2 | 
| 2 | 3 | 10 |   3 | 3 | 
+------+------+------+--------------+------+ 

注意,@一的前3列的值保持不变,一直到mysql的到达@a := @a +1,之后@a有一个新的价值

因此,也许您的查询应该是

set @a = 0; 
select @temp := @a, ..., @a := _id2 
where 
    ((_id2 = Progress.id AND _id1 NOT IN (SELECT id FROM Progress) AND @temp =_id1) 
    ... 
etc... 
+0

感谢您的澄清。无论如何,我怎么能解决这个问题(即使这是可能的一个单一的查询)。 – Spotlight 2013-04-23 16:36:58