我的SQL语法有问题。我想添加一个介于10000和99999之间的随机电话号码。到目前为止,我有这个查询,但是我无法在PHPMyAdmin中运行它:
SELECT round(RAND()*99999) AS `NUM`
WHERE `NUM` NOT IN (SELECT `PHONE_NUMBER` FROM `PHONE`);
这是错误:
1064-第1行上“ WHERE
NUM
NOT IN(从PHONE_NUMBER
中选择PHONE
的地方(选择{{1}})附近的语法错误”
答案 0 :(得分:3)
您可以这样做:
SELECT NUM
FROM (SELECT round(RAND()*99999) AS `NUM`) x
WHERE `NUM` NOT IN (SELECT `PHONE_NUMBER` FROM `PHONE`);
NUM
在WHERE
子句中未知。而且,如果没有WHERE
,就不会拥有FROM
。
答案 1 :(得分:0)
@GordonLinoff答案的一个问题是,它可能不返回任何值,而是返回另一个表中不存在的数字。有两种解决方法:使用存储的函数或使用数字表。这是通过存储的函数来完成的:
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
答案 2 :(得分:0)
不上班。最接近的方法是这样,通过包装到子查询中来保护您的第一个查询:
SELECT NUM
FROM (SELECT 10000 + ROUND(RAND()*89999) AS NUM) AS SUBQ
WHERE NUM NOT IN (SELECT PHONE_NUMBER FROM PHONE);
但是,尽管它确实选择了10000到99999之间的一个数字,但它只能在之后检查其不存在。如果检查失败,查询将不返回任何内容,而您将不得不重试(或使用UNION使其复杂化,但仍不能绝对保证)。
另一种可能性是生成另一个 all 编号在10000和99999之间的表,并运行LEFT JOIN
,要求右侧为NULL。然后,您必须从该结果中选择一个随机条目;我不确定,但是在这种情况下,可能选择了九十万个之后,您可能必须先运行ORDER BY RAND(),然后执行LIMIT 1来提取一条记录。这将是昂贵的(但请参阅最后的答案)。
如果电话表几乎为空,最有效的方法是使用存储过程,并保持运行第一个查询(或先生成查询再生成查询),直到成功为止。电话表稀疏,应该在很少的尝试中进行。
否则,您可以用所有数字预填充电话表(该表已经被大量填充,因此这不是很大的额外费用),并添加一列指出该数字是“免费”的列。然后,您从表中选择一个随机条目,条件是自由标记产生true。在这种情况下,您需要阅读this answer。