我有 2 个表如下(这是一个 phpMyAdmin 转储,这就是它具有 ALTER TABLE 的原因):
CREATE TABLE IF NOT EXISTS `definition` (
`id` int(10) unsigned NOT NULL,
`page_id` int(10) unsigned NOT NULL,
`title` varchar(255) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=2621401 ;
CREATE TABLE IF NOT EXISTS `definition_used` (
`id` int(10) unsigned NOT NULL,
`word` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`ts_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=65 ;
ALTER TABLE `definition`
ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `page_id` (`page_id`), ADD KEY `title` (`title`);
ALTER TABLE `definition_used`
ADD PRIMARY KEY (`id`), ADD KEY `word` (`word`,`ts_created`);
ALTER TABLE `definition`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2621401;
ALTER TABLE `definition_used`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=65;
而且我需要从中获取一个唯一的随机词,因为我在definition
表上有数百万条记录,RAND
直接使用不是一种选择。
我确实有一个查询会得到一个随机词,就是这个:
SELECT r1.title
FROM definition AS r1
JOIN (SELECT (RAND() * (SELECT MAX(id)
FROM definition
)
) AS id
) AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1
但是,这将根据 id 选择单词,而无需进行任何我需要的检查。现在假设它随机选择id
了 200 万个单词,并且没有给出可用的单词,r1.id >= r2.id
所以我没有得到任何结果,但如果它更少,它可能会产生很多结果。
现在我已经归结为:
SELECT a.title
FROM definition a
LEFT JOIN definition_used b
ON a.title = b.word
WHERE (b.id IS NULL OR (b.ts_created = CURDATE())) AND
LOWER(a.title) LIKE @message
LIMIT 1
从表中definition_used
我需要确保 aword
今天没有使用,以便被重用,所以 aword
可以有多个条目,只要ts_created
不与同一日期冲突,因此我检查:
(b.id IS NULL OR (b.ts_created = CURDATE()))
然而出来的词有 0 随机化,我怎样才能从列表中得到一个随机词?
我已经看到了一些其他问题,您可以在其中使用最大 id 定义随机条目的单个表来执行此操作,但除了单词本身之外,我没有从definition
表引用到表。definition_used
- 简而言之,我需要能够从可用的未使用词中选择一个随机词,这是我不知道该怎么做的。