我有一个包含n张图片的mySQL表。
+------------+--------------+
| picture_id | picture_name |
+------------+--------------+
| 1 | ben.jpg |
| 2 | nick.jpg |
| 3 | mark.jpg |
| 4 | james.jpg |
| .. | ... |
| n | abraham.jpg |
+------------+--------------+
对于Web应用程序,我需要同时显示2张图片,用户可以在其中投票选择一张图片或另一张图片。投票后,用户获得一组新的两张图片。
(应用程序使用界面)
+---------------------+--------------------+
| Vorte for picture 1 | Vote for picture 2 |
+---------------------+--------------------+
我想避免尽可能多地显示相同的组合。我可以创建一个包含所有可能组合的帮助表。
+----------------+--------------+--------------+
| combination_id | picture_id_1 | Picture_id_2 |
+----------------+--------------+--------------+
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 4 |
| 4 | 1 | 5 |
| .. | .. | .. |
| (n^2-n)/2 | .. | .. |
+----------------+--------------+--------------+
但是对于100张图片,那将是(100 ^ 2 - 100)/ 2 = 4950(编辑)行,并且对于每个添加的图片,表将以指数方式增长。 (我认为这在今天的计算中不是一个大问题)
但是我如何以用户总是看到尽可能少的重复项的方式查询此表。
预期结果:
run 1: picture_id's = 4,5 (any numbers between 1 and n)
run 2: picture_id's = 2,7
run 3: picture_id's = 5 and 20
...
答案 0 :(得分:0)
DEMO:http://rextester.com/VNWIOA4679(添加100张样本)2秒查询1个用户没有任何索引。
我认为不需要辅助表,因为可以使用适当的索引轻松构建数据。在1000张图片中,您可以查看用户可以投票的499,500种组合。仍然可以在数据库构造中轻松管理,因为我们在设定级别而非记录级别上操作。
这是假设我自己的桌面结构的一种方式。我无法想出一种更有效的方式来存储/处理数据。
使用此方法添加新图片时,查询将生成越来越大的组合集,但始终排除用户已投票的组合。没有代码更改新的图片,没有再生集只是处理每次用户没有做出选择。
Create table SO46205797_Pics(
PICID int);
Insert into SO46205797_Pics values (1);
Insert into SO46205797_Pics values (2);
Insert into SO46205797_Pics values (3);
Insert into SO46205797_Pics values (4);
Insert into SO46205797_Pics values (5);
Insert into SO46205797_Pics values (6);
Insert into SO46205797_Pics values (7);
Create table SO46205797_UserPicResults (
USERID int,
PICID int,
PICID2 int,
PICChoiceID int);
Insert into SO46205797_UserPicResults values (1,1,2,1);
Insert into SO46205797_UserPicResults values (1,1,3,1);
Insert into SO46205797_UserPicResults values (1,1,4,4);
魔术发生在这里,上面只是数据设置。
SELECT A.PICID, B.PICID, C.PICChoiceID
FROM SO46205797_Pics A
INNER JOIN SO46205797_Pics B
on A.PICID < B.PICID
LEFT JOIN SO46205797_UserPicResults C
on A.PICID = C.PicID
and B.PICID = C.PICID2
and C.USERID = 1
WHERE C.userID is null;
请注意,如果我们消除C.userID为null部分,那么我们会看到所有可能的组合(对于user1)(注意我将ID 1,2处理为ID 2,1我认为你是蚂蚁) 2张照片以及用户选择的照片。由于我们不想再次显示该选项,因此我们使用c.userID为null来排除用户已选择的组合。
同样,在将数据保存到userPicResults时,您需要确保PICID1始终小于PICID2。
另一种方法是使用不存在的可能稍微快一些。
显然,对于SOID205797_UserPicResults,以及SO46205797_Pics作为PK的PICID索引,USERID,PICID,PICID2以及该顺序的索引对于SO46205797_UserPicResults以及PICID的索引都是有益的(我可能会将其作为组合PK)。SELECT A.PICID, B.PICID
FROM SO46205797_Pics A
INNER JOIN SO46205797_Pics B
on A.PICID < B.PICID
WHERE not exists (SELECT *
FROM SO46205797_UserPicResults C
WHERE A.PICID = C.PicID
and B.PICID = C.PICID2
and C.USERID = 1);
我考虑为每个用户维护每个图像的父/子关系;但这种方法并不存储所有组合的选择。
答案 1 :(得分:0)
这个应用程序的目标是让人们投票反对另一张图片,对吧?然后你需要有一些投票结果表:
vote_results:
| vote_id | user_id | vote_up_picture_id | vote_down_picture_id | ...
然后,根据此表中的数据,您可以轻松地向用户显示对象,但他还没有看到:
select first.picture_id, second.picture_id
from pictures as first, pictures as second
where not exists(
select * from vote_results v
where (v.vote_up_picture_id = first.picture_id and v.vote_down_picture_id = second.picture_id)
or (v.vote_up_picture_id = second.picture_id and v.vote_down_picture_id = first.picture_id)
) and first.picture_id != second.picture_id
order by rand()
limit 1
PS。如您所见,在help_id
的辅助表中没有必要