首页 > 解决方案 > mysql查询从3个类别中获取随机项目

问题描述

我有一个包含 3 种数据类型(文本、图像、视频)的 mysql 表 $type 列保存数据的类型。(类型 = 1 用于文本,2 用于图像,3 用于视频)

我的要求是需要从表中获取 20 条记录的随机数据,它应该有 8 个文本、8 个图像和 4 个视频。

前 2 条记录的结果也应该是图像和下 1 个视频和下 2 个文本,然后再次重复。

标签: mysql

解决方案


这是一个 MariaDB 10.1 查询,可以满足您的需求。它首先随机选择 8 个文本、4 个视频和 8 个图像。然后,它将行号分配给每种类型的数据,并使用这些行号将值组合在一起(2 个文本、1 个视频、2 个图像)以及ELT在组内按图像、视频和文本排序的功能。

SELECT type, value
FROM (
SELECT value, @rn := IF(type = @type, @rn + 1, 1) AS row, @type := type AS type
FROM (
(SELECT type, value
 FROM data
 WHERE type = 1
 ORDER BY RAND()
 LIMIT 8)
UNION ALL
(SELECT type, value
 FROM data
 WHERE type = 2
 ORDER BY RAND()
 LIMIT 8)
UNION ALL
(SELECT type, value 
 FROM data
 WHERE type = 3
 ORDER BY RAND()
 LIMIT 4)
ORDER BY ELT(type, 3, 1, 2)
) d
CROSS JOIN (SELECT @rn := 0, @type := '') r) v
ORDER BY CASE WHEN type = 1 OR type = 2 THEN (row - 1) DIV 2
              ELSE row - 1 END,
         ELT(type, 3, 1, 2)

在 dbfiddle 上做了一个演示,展示了这一点。

如果您升级到 MariaDB 10.2,您可以省去变量并使用ROW_NUMBER

WITH cte AS 
((SELECT type, value, ROW_NUMBER() OVER (PARTITION BY type ORDER BY RAND()) AS row
 FROM data
 WHERE type = 1
 LIMIT 8)
UNION ALL
(SELECT type, value, ROW_NUMBER() OVER (PARTITION BY type ORDER BY RAND()) AS row
 FROM data
 WHERE type = 2
 LIMIT 8)
UNION ALL
(SELECT type, value, ROW_NUMBER() OVER (PARTITION BY type ORDER BY RAND()) AS row 
 FROM data
 WHERE type = 3
 LIMIT 4)
)
SELECT type, value
FROM cte
ORDER BY CASE WHEN type = 1 OR type = 2 THEN (row - 1) DIV 2
              ELSE row - 1 END,
         ELT(type, 3, 1, 2)

这个查询也在我的演示中演示


推荐阅读