2017-04-13 64 views
-3

我有一个表格,结构如下。 该表主要记录性别= 1的地方。MySQL获得加权结果

我正在寻找一个解决方案来获得结果集,其中60%的记录顶部有性别= 1,40%与性别= 2混合,有序通过人气desc。 性别= 2的成员数量少得多,这意味着结果集应该只有性别= 1的记录。

会员表

id | nickname | gender | popularity 
1 | jake  | 1  | 80 
2 | mike  | 1  | 88 
3 | dave  | 1  | 75 
4 | jenny | 2  | 85 
5 | peter | 1  | 83 
6 | nina  | 2  | 88 
7 | mister | 1  | 77 
8 | drake | 1  | 80 

结果应该是这样的,它必须满足不了确切加权列表。目标是看到两性的混合结果。

id | nickname | gender | popularity 
2 | mike  | 1  | 88 
5 | peter | 1  | 83 
6 | nina  | 2  | 88 
1 | jake  | 1  | 80 
8 | drake | 1  | 80 
4 | jenny | 2  | 85 
7 | mister | 1  | 77 
3 | dave  | 1  | 75 

我到目前为止的最好成绩是(它不照顾有关40:60分):

SET @rank=0; 
SET @rank2=0; 
SELECT * FROM (
SELECT @rank:[email protected]+1 AS rank, q.* FROM (SELECT * FROM test WHERE gender = 1  ORDER BY popularity DESC) AS q 
UNION 
SELECT @rank2:[email protected]+1 AS rank, q.* FROM (SELECT * FROM test WHERE gender = 2 ORDER BY popularity DESC) AS q 
) AS r ORDER BY rank; 
+1

这是一个需求规格说明,而不是一个问题。请提出问题,并分享您的尝试。 – Shadow

+0

为了澄清,您要求我们提供一个列表,其中最多40%的条目是“性别= 2”,其余是“性别= 1”?或者你是否要求我们制作一份仅按照受欢迎程度排序的列表,如果您期望没有返回“性别= 2”条目,尽管它可能在理论上是可能的? – toonice

+0

@toonice是的我要求提供一个列表,显示40%的条目,其中性别= 2,其余为性别= 1 – nenad007

回答

0

请尝试...

SET @gender1Count = SELECT COUNT(*) 
        FROM tblMember 
        WHERE gender = 1; 

SET @gender2Count = SELECT COUNT(*) 
        FROM tblMember 
        WHERE gender = 2; 

SET @totalCount = SELECT COUNT(*) 
        FROM tblMember; 

SELECT id AS id, 
     nickname AS nickname, 
     gender AS gender, 
     popularity AS popularity 
FROM tblMember 
JOIN (SELECT id AS id 
     FROM tblMember 
     WHERE gender = 1 
     ORDER BY popularity DESC 
     LIMIT CASE 
      WHEN @gender1Count > @totalCount * 3/5 
       ROUND(@gender2Count * 3/2) 
      ELSE 
       @gender1Count 
      END 
     UNION 
     SELECT id AS id 
     FROM tblMember 
     WHERE gender = 2 
     ORDER BY popularity DESC 
     LIMIT CASE 
      WHEN @gender1Count > @totalCount * 3/5 
       @gender2Count 
      ELSE 
       ROUND(@gender1Count * 2/3) 
      END 
    ) nominees ON tblMember.id = nominees.id 
ORDER BY popularity DESC; 

上面会给你一个列表,其中60%的条目是gender = 1和40%是gender = 2。请注意,这与gender = 1余额gender = 2(或占总列表的40%或更多的gender = 2和余额gender = 1)的总列表的60%或更多不同。

它通过形成一个列表,其中gender等于1并将其按照popularity的降序排序。然后它通过检查gender = 1成员的数量是否超过列表的60%(3/5)来确定它将使用LIMIT从该列表中获取的最多条目的数量。如果确实如此,那么我们将需要将要检索的gender = 1记录的数量减少到gender = 2成员的计数的3/2倍。然后返回所选记录的id

(对于那些分数不高的人来说,速度很快,40%与2/5(五分之二)相同。如果gender = 2有五分之二的最终名单,那么gender = 1必须有另外五分之三3/5)为了找到列表的3/5的大小,我们从已知的2/5(计数为gender = 2)开始,并将其除以2,以便我们知道列表的1/5的大小。然后可以将此1/5乘以3以确定有多少记录将构成我们列表的3/5(60%)。)

类似的逻辑用于形成要包括在最终的成员列表中的gender = 2成员名单。

(请注意,每个列表末尾的记录可能具有与其性别对应于每个列表的最受欢迎的排除的成员相同的流行值,如果没有任何子列表形成两个列表那些或未选择将是任意的(并且基本上半随机)的选择。)

的两个列表然后使用在什么是简单类型的垂直加入UNION操作者接合。 (注:比较熟悉的INNER JOIN,LEFT JOIN等,均为横向连接)。

然后在我们的原始表格中对我们的id合并列表执行内部JOIN,给我们我们的60%/ 40%列表。最后,这个清单按照popularity的降序排列。

如果您有任何问题或意见,请随时发布相应评论。

+0

代码略有更新。 – toonice

+0

谢谢,在修正了第一个错误之后,必须在SET(SELECT COUNT(*)FROM test WHERE gender = 1)中使用括号。我仍在搜索什么导致语法错误与indind LIMIT和CASE有关,我已经添加THEN但仍然没有加工。 – nenad007