如何使用 group by 子句选择随机行?

Posted

技术标签:

【中文标题】如何使用 group by 子句选择随机行?【英文标题】:How to select a random row with a group by clause? 【发布时间】:2015-04-15 09:19:21 【问题描述】:

我有下表

SQLFiddle

我正在尝试做的是选择三个随机图像,但要确保没有两个图像具有相同的对象,我尝试做的是执行 GROUP BY 和 ORDER BY rand() 但是失败了,因为它总是给我 cat1.jpg、dog1.jpg、box1.jpg(路径以 1 结尾的所有图像,而不是其他图像)

小提琴包括我运行的查询以及它是如何不工作的。

【问题讨论】:

【参考方案1】:

您需要的是一个随机聚合函数。目前的RDBMS中通常没有这样的功能。

类似的问题有been asked。

所以基本思想是打乱元素,然后分组,然后为每个组选择每个组的第一行。如果我们修改链接上提供的答案之一,我们会得到这个。

select object_id, name, image_path
from
  (SELECT images.image_path AS image_path, objects.id AS object_id, objects.name
  FROM objects LEFT JOIN images ON images.object_id = objects.id
  ORDER BY RAND()) as z
group by z.object_id, z.name

【讨论】:

您的链接似乎指向了一个询问表别名的无关问题。我一直在尝试让这个示例代码正常工作,并将其调整到我的表格设置中,但它每次都返回完全相同的数据。返回的数据是每个分组项的第一行,而不是随机行。这个功能在更高版本的 mysql 中是否发生了变化?【参考方案2】:

您无法获得随机图像,因为 MySQL 总是根据插入时间(先到先得)返回该数据,即内部顺序。

但您可以使用以下方法 (fiddle) 获得随机结果:

SELECT images.image_path AS image_path, objects.name 
FROM objects 
LEFT JOIN 
 ( 
   SELECT object_id, 
      SUBSTRING_INDEX(GROUP_CONCAT(image_path order by rand()), ',', 1) AS image_path
   FROM images
   GROUP BY object_id
 ) as images
ON images.object_id = objects.id 
GROUP BY objects.name 

如果对象表上存在限制性 WHERE 条件,则在先加入和 GROUP_CONCAT 时可能会获得更好的性能。

【讨论】:

这很好用!它在非常大的表上确实存在一些性能问题,但它实际上从一组返回随机数据。另一个回复(有更多选票!)没有为我返回随机数据,我只是花了几个小时试图让它工作。谢谢!【参考方案3】:

我认为应该这样做:

随机排序() 限制 1 个

【讨论】:

以上是关于如何使用 group by 子句选择随机行?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用纯 SQL 选择 N 个随机行?

我们如何在具有GROUP BY子句的查询中选择非聚合列,而GROUP BY子句在功能上不依赖于GROUP BY子句中的列?

如何从没有数字主键的表中有效地选择随机行

如何从 SQL 数据库表中选择随机行? [复制]

选择的字段不包含在 GROUP BY 子句中,那么这个 Access 查询如何成功运行?

如何在 Postgres 中从具有非均匀分布的表中选择随机行?