获得2张图片的最独特组合

时间:2017-09-13 19:51:48

标签: mysql

我有一个包含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
... 

2 个答案:

答案 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

的辅助表中没有必要