2017-09-13 41 views
-1

我有一个mySQL表,可容纳n张图片。获取2张图片的最独特的组合

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

你是怎么从450? “每增加一张照片”是什么意思?你打算也做3套,4套等?你的桌子如何处理这种随意的变化? – David

+0

你在哪里存储用户结果?只需自己加入ID为1的ID小于2的ID,这样你就可以得到A xQbert

+0

@David想一想乘法表。数字从1到10,乘以从1到10的每个数字。有10^2个可能的结果,一半是重复的。 10是自身的乘法。 随着每一次添加的图片,我的意思是在数据库中的图片总数。我总是计划最多显示2张图片 –

回答

0

DEMO:http://rextester.com/VNWIOA4679(加入100个PIC样品)2秒查询1用户的w/o的任何索引。

我认为不需要辅助表,因为数据可以通过适当的索引轻松构建。在你正在查看的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是空部分,那么我们看到的所有可能的组合(用户1)(注意我把ID 1,2相同的ID 2,1我想想你蚂蚁)为2张照片和用户选择了哪些。由于我们不想再次显示该选项,因此我们使用c.userID为空来排除用户已经选择的组合。

将数据保存到userPicResults时,还需要确保PICID1始终小于PICID2。

一个不同的方法来做到这一点是使用不存在,可能会稍微快一点。

明显地在USERID,PICID,PICID2上的索引,并且按照SO46205797_UserPicResults和PIC46的索引作为PK,顺序将会是有利的(我可能使它成为组合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); 

我考虑为每个用户维护每个图像的父/子关系;但是这种方法不存储所有组合的选择。

+0

我们可以通过RAND()和限制1在这两种以获得用户已不是尚未作出选择一个随机的2张图片。或者我们可以按索引排序并允许它们按照图片顺序处理。 – xQbert

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。正如你看到的,有在助手表不需要与COMBINATION_ID