我把它放在 SQLFiddle 上,它按预期工作,但在大学 MySQL 引擎上,它的工作方式不同: http://sqlfiddle.com/#!9/9d975f/3
我有一个包含单词及其类别的列表:
id, word, category
1, red, color
2, blue, color
3, brick, item
4, rock, item
5, hat, item
6, glove, item
7, cape, item
8, cup, item
9, love, feeling
... etc
我需要 8 个单词,其中前 4 个是颜色和项目的混合,但后 4 个只是项目,并且单词必须是随机选择的且是唯一的。
例如:蓝色、帽子、岩石、红色、砖 block 、手套、杯子、斗篷(颜色、元素、元素、颜色、元素、元素、元素、元素)
我无法在单个查询中完成此操作,因此我首先运行一个查询来获取前半部分的 ID 列表,例如 1、2、4、5(红色、蓝色、岩石、帽子)
这有效:
SELECT * FROM word WHERE id IN (1, 2, 4, 5) ORDER BY RAND()
总是以随机顺序给我单词 1、2、4 和 5。但是,当在 UNION 中用作子查询时:
SELECT * FROM (SELECT * FROM word WHERE id IN (1, 2, 4, 5) ORDER BY RAND() ) a
UNION
SELECT * FROM (SELECT * FROM word WHERE id NOT IN (1, 2, 4, 5) AND category='item' ORDER BY RAND() LIMIT 4) b
前 4 个单词始终按顺序排列,例如:1、2、4、5、8、3、7、6。但是,如果我指定限制:
SELECT * FROM (SELECT * FROM word WHERE id IN (1, 2, 4, 5) ORDER BY RAND() LIMIT 4) a
UNION
SELECT * FROM (SELECT * FROM word WHERE id NOT IN (1, 2, 4, 5) AND category='item' ORDER BY RAND() LIMIT 4) b
它完全按照预期工作。我按随机顺序得到红色、蓝色、岩石和帽子,然后按随机顺序再得到 4 个元素,不包括岩石和帽子。
我知道 UNION 有一个删除重复项的规则列表,但我很困惑为什么包含限制会改变行为。
理想情况下,我想在单个查询中完成此操作,但我不知道如何在联合的第二半部分执行 NOT IN,该联合的第二半部分引用了在联合的第一半部分中选择的单词。
最佳答案
正如您所注意到的,UNION
具有重复数据删除功能。此函数通常与哈希合并一起使用。它使子查询中有助于合并的任何 ORDER BY
子句的效果无效。 (一些 DBMS 说“您不能在绑定(bind)到 UNION
的子查询中使用 ORDER BY
”,但 MySQL 允许您这样做。)
您可以尝试类似的方法来解决该问题。
SELECT word
FROM (
SELECT word, RAND() random FROM word WHERE id IN (1, 2, 4, 5)
UNION
SELECT word, 1.0+RAND() random FROM word WHERE id NOT (1, 2, 4, 5)
) w
ORDER BY random
这将在外部查询中进行排序,而不是在子查询中,并将实现您想要的排序。
关于mysql - UNION 与 ORDER BY RAND() 仅适用于 MySQL 上的 LIMIT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45684883/