MySQL - 选择不同用户的N个随机行,其中只包含小于或等于X的值

时间:2017-02-14 16:24:45

标签: mysql sql

我想从表中选择N个随机行,但在所有这些行中,特定值可能只出现X次。

表"评论":

*--------------------*
| ID | CODE_REVIEWER |
*--------------------*
| 1  |    2          |
| 1  |    3          |
| 1  |    4          |
*--------------------*

表"用户" (我遗漏了很多不重要的东西:

*----*
| ID |
*----*
| 1  |
| 2  |
| 3  |
| 4  |
| 5  |
*----*

示例输出: 对于X = 3:

*-----------*
| REVIEWER  |
*-----------*
|     4     |
|     1     |
|     5     |
*-----------*

对于X = 2:

*-----------*
| REVIEWER  |
*-----------*
|     1     |
|     5     |
|     3     |
*-----------*

对于X = 1(空):

*-----------*
| REVIEWER  |
*-----------*

因此,它必须是一个ResultSet,其中包含一些与ID X不同的ID,但这些ID可能只出现在"表2"作为" code_reviewer" N次。 所以每个人都可以成为"评论家"对于3个人,可以由3个人审查

谢谢!

修改 这是我到目前为止所得到的:

select newid from (select id, count(*) as num from (select * from users
where id != ?) as users group by id order by RAND() LIMIT ?) as sb
where num < 3 and newid not in (select code_reviewer from reviews where id = ?)

它完美无缺,除此之外它有时会返回

*---*
| 2 |
| 1 |
| 2 |
*---*

(包含两次,不应该这样)

2 个答案:

答案 0 :(得分:1)

不幸的是,我知道MSSQL而不是MySQL。我将尝试使用MSSQl进行回答,希望这将引导您朝着正确的方向前进。

我使用变量来确定应该返回多少行,然后使用一个简单的NEWID作为随机函数。 (据我所知,您可以在MySQL中订购RAND()而不是NEWID())

declare @userId int
select @userId = 1
declare @existingReviewCount int
select @existingReviewCount = COUNT(*) from Reviews where Id = @userId
declare @requiredRowCount int
select @requiredRowCount = 3 - @existingReviewCount

select top (@requiredRowCount) Id from Users
where @userId != Id
order by NEWID()

现在将@userId替换为1,它将返回一个空集。

答案 1 :(得分:1)

这似乎基本上是每组前n个问题。有几种方法可以解决这个问题。这是一种快速而肮脏的方式,它将为您提供所需的逗号分隔的ID列表。如果你想在你的代码中爆炸,你就可以了。

select u.*, 
    -- r_counts.cnt as reviews_count,
    substring_index(
        group_concat(u_rev.id order by rand()),
        ',',
        greatest(3-r_counts.cnt,0)) as reviewers
from users u
join users u_rev on u.id != u_rev.id
left join (
    select u.id, count(r.id) as cnt
    from users u
    left join reviews r on u.id = r.id
    group by u.id
) r_counts on r_counts.id = u.id
left join (
    select u.id, count(r.id) as cnt
    from users u
    left join reviews r on u.id = r.reviewer
    group by u.id, r.reviewer
) as did_review_counts
on did_review_counts.id = u_rev.id
where u.id = 11
and did_review_counts.cnt < 3
group by u.id;

如果你需要另一种结果,谷歌“每组mysql顶部n”,并查看那里的一些解决方案。

注意:以上3就是您的评论号码目标。编辑:现在需要一次只运行1个。然后在每次审核完成后重新运行。