DELIMITER //
DROP FUNCTION IF EXISTS get_random_phone //
CREATE FUNCTION get_random_phone(min INT, max INT) RETURNS INT
NOT DETERMINISTIC
BEGIN
DECLARE num INT;
DECLARE finished INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
REPEAT
SET num = min + FLOOR(RAND() * (max - min + 1));
SELECT phone_number INTO num FROM phone WHERE phone_number = num;
UNTIL finished = 1
END REPEAT;
RETURN num;
END //
然后您的查询就变成
SELECT get_random_phone(10000, 99999)
或者,您可以创建一个数字表 LEFT JOIN 在电话号码表中,只选择不匹配的行,然后按排序 RAND() 以及使用 LIMIT 1 只返回一个结果。但是请注意,如果没有索引,这可能会非常慢 num 以及 phone_number .
CREATE TABLE numbers (num INT PRIMARY KEY) AS
SELECT n1.n + n10.n*10 + n100.n*100 + n1000.n*1000 + n10000.n*10000 AS num FROM
(SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) n1
CROSS JOIN
(SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) n10
CROSS JOIN
(SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) n100
CROSS JOIN
(SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) n1000
CROSS JOIN
(SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) n10000
ORDER BY NUM
在这种情况下,您的查询将是:
SELECT num
FROM numbers
LEFT JOIN phone ON phone.phone_number = numbers.num
WHERE phone.phone_number IS NULL AND num BETWEEN 10000 AND 99999
ORDER BY RAND()
LIMIT 1
SELECT NUM
FROM (SELECT round(RAND()*99999) AS `NUM`) x
WHERE `NUM` NOT IN (SELECT `PHONE_NUMBER` FROM `PHONE`);
``` `NUM` 现在还不知道 `WHERE` 条款。而且,你不能有一个 `WHERE` 没有一个 `FROM` .
SELECT NUM
FROM (SELECT 10000 + ROUND(RAND()*89999) AS NUM) AS SUBQ
WHERE NUM NOT IN (SELECT PHONE_NUMBER FROM PHONE);
但是,虽然这确实选择了一个介于10000和99999之间的数字,但它只能在之后检查它是否不存在。如果检查失败,查询将不返回任何内容,您必须重试(或者使用联合使其复杂化,这仍然不能提供绝对的保证)。 另一种可能是生成另一个表,其中所有数字都在10000到99999之间,然后运行 LEFT JOIN 请求右侧为空。然后你必须从结果中随机选择一个条目;我不确定,但在这种情况下,您可能需要运行order by rand(),然后运行limit 1来提取一条记录,然后可能选择90万条记录。这将是昂贵的(但见最后的答案)。 如果phone表几乎是空的,最有效的方法是使用存储过程并继续运行第一个查询(或者在生成之后执行一个检查),直到它成功为止,如果phone表是稀疏的,它应该在很少的尝试内完成。 否则,您可以用所有号码预先填充电话表(该表已被大量填充,因此这不是一个很大的额外成本),并添加一列声明该号码是“免费”的。然后从表中选择一个随机条目,条件是自由标记产生true。在这种情况下,你会想读这个答案。
3条答案
按热度按时间oknwwptz1#
@gordonlinoff answer的一个问题是,它可能不返回任何内容,而返回另一个表中不存在的数字。有两种方法可以解决这个问题:使用存储函数,或者使用数字表。以下是如何使用存储函数:
然后您的查询就变成
或者,您可以创建一个数字表
LEFT JOIN
在电话号码表中,只选择不匹配的行,然后按排序RAND()
以及使用LIMIT 1
只返回一个结果。但是请注意,如果没有索引,这可能会非常慢num
以及phone_number
.在这种情况下,您的查询将是:
nwlls2ji2#
你可以做:
zrfyljdw3#
不去上班。最接近的方法是这样,通过 Package 到子查询中来保护第一个查询:
但是,虽然这确实选择了一个介于10000和99999之间的数字,但它只能在之后检查它是否不存在。如果检查失败,查询将不返回任何内容,您必须重试(或者使用联合使其复杂化,这仍然不能提供绝对的保证)。
另一种可能是生成另一个表,其中所有数字都在10000到99999之间,然后运行
LEFT JOIN
请求右侧为空。然后你必须从结果中随机选择一个条目;我不确定,但在这种情况下,您可能需要运行order by rand(),然后运行limit 1来提取一条记录,然后可能选择90万条记录。这将是昂贵的(但见最后的答案)。如果phone表几乎是空的,最有效的方法是使用存储过程并继续运行第一个查询(或者在生成之后执行一个检查),直到它成功为止,如果phone表是稀疏的,它应该在很少的尝试内完成。
否则,您可以用所有号码预先填充电话表(该表已被大量填充,因此这不是一个很大的额外成本),并添加一列声明该号码是“免费”的。然后从表中选择一个随机条目,条件是自由标记产生true。在这种情况下,你会想读这个答案。