繁体   English   中英

WHERE子句中的MySQL变量

[英]MySQL variable in WHERE clause

我需要一个查询,该查询可以根据用户关注的电视节目查找用户推荐的电视节目。 为此,我有下表:

  • 包含“非常接近”的表“ Progress显示用户正在关注以及所看到的情节的百分比(为解决此问题,我们可以假设我在数据库中只有一个用户)

  • Suggested包含_id1_id2value (价值是展会与ID =之间的连接的强度_id1和使用id =显示_id2 :更多的value是巨大的,越节目有共同的东西)。 请注意,此表中应用了交换属性,因此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)

它可以工作,但是非常慢。

您尝试使用xor是明智的。 如果要获取不匹配的值,则要使用按位的XOR,即^

Progress.id ^ _id1 ^ _id2

3 ^ 2 ^ 3 = 2

2 ^ 2 ^ 3 = 3

您可以使用此技巧来建立联接并真正简化查询(消除“或”和“非”,并在一个不带变量的查询中完成)。


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

分解它。 我创建了一个有一个用户的用户表(但是该解决方案可以与多个用户一起使用。)

选择和加入进度很简单。 建议的联接使用IN替代使用OR编写它

与showcache的联接是按位XOR发生的地方。 该ID之一链接到progress.show_id,我们想使用另一个。

它确实包括“不参加”,以从结果中排除已经观看的节目。 我可以将其更改为不存在? 但这种方式似乎更清晰。

您要在where子句中设置两次@a的值,这意味着查询实际上会简化为:

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

MySQL按照第一个遇到的顺序评估变量赋值,因此您应保留@a常量直到该子句的END,然后分配一个新值,例如

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 |
+------+------+------+--------------+------+

请注意,前三列中@a := @a +1的值保持不变,直到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...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM