簡體   English   中英

如何插入 MySQL 表中不存在的隨機數?

[英]How to insert a random number which is not present in MySQL table?

主要查詢

$sql = "INSERT INTO foldertable ( folderid )
             SELECT (
                        SELECT random_num
                        FROM (
                                SELECT FLOOR(RAND() * 4 + 1) AS random_num
                        ) AS numbers_mst_plus_1
                        WHERE random_num NOT IN (
                            0,1
                        )
                                  )";

問題

它插入一個隨機數。 但有時它只是簡單地插入 0。

我想什么?

當下面的 SQL 返回一個等於 0 或 1 的數字時,它是插入零。

SELECT random_num
                        FROM (
                                SELECT FLOOR(RAND() * 4 + 1) AS random_num
                        ) AS numbers_mst_plus_1
                        WHERE random_num NOT IN (
                            0,1
                        )

我想要的是?

select 查詢到 select 一個數字,直到它對於該列是唯一的。

嘗試:-

我創建了一個選擇 1,2,3,4,5 的 select 語句

SELECT random_num
        FROM (
           SELECT 1 AS random_num
           UNION 
           SELECT 2 AS random_num
           UNION 
           SELECT 3 AS random_num
           UNION 
           SELECT 4 AS random_num
           UNION 
           SELECT 5 AS random_num
       ) AS numbers_mst_plus_1

然后嘗試在 INSERT QUERY 中實現它

$sql = "INSERT INTO foldertable ( folderid )
            SELECT (SELECT random_num FROM (SELECT 1 AS random_num UNION SELECT 2 AS random_num) AS temp_table WHERE random_num NOT IN (1) LIMIT 1
                    )

上面的查詢總是將 2 插入到表中,我很高興。 然后我想如果NOT IN中同時存在 1 和 2 (真實的,例如Not in Clause 包含表中存在的所有文件夾 id)

問題就在那里 -----

$sql = "INSERT INTO foldertable ( folderid )
            SELECT (SELECT random_num FROM (SELECT 1 AS random_num UNION SELECT 2 AS random_num) AS temp_table WHERE random_num NOT IN (1 , 2) LIMIT 1
                    )
            ";

現在它再次在folderid列中輸入0

所以我在其中添加了WHERE CLAUSE

$sql = "INSERT INTO foldertable ( folderid )
            SELECT (SELECT random_num FROM
                                        (SELECT 1 AS random_num UNION SELECT 2 AS random_num UNION SELECT 3 AS random_num )
                                        AS temp_table
                                        WHERE random_num
                                        NOT IN (
                                                SELECT folderid FROM foldertable
                                                )
                                        LIMIT 1
                    )
            WHERE ((SELECT COUNT(*) FROM foldertable) < 3)
            ";

因此,如果使用了所有 ID,現在它不會添加新行。

但真正的痛苦是寫作

           SELECT 1 AS random_num
           UNION 
           SELECT 2 AS random_num
           UNION 
           SELECT 3 AS random_num
           UNION 
           SELECT 4 AS random_num
           UNION 
           SELECT 5 AS random_num
           .... 100000000 times 
           UNION
           SELECCT 100000006 AS random_num

所以這不值得時間

所以GOD FOR LOOP來了

$randomNoString = "";
    for ($i=0; $i < ($maxFolderId - $minFolderId + 1 ); $i++) { 
        if($i === 0){
            $randomNoString ="SELECT ".($minFolderId + $i) . " AS random_num" ;
        }
        else {
            $randomNoString =  $randomNoString ." UNION " . "SELECT ".($minFolderId + $i) . " AS random_num";
        }
    }

$sql = "INSERT INTO foldertable ( folderid )
        SELECT (SELECT random_num FROM
                                    ({$randomNoString})
                                    AS temp_table
                                    WHERE random_num
                                    NOT IN (
                                            SELECT folderid FROM foldertable
                                            )
                                    LIMIT 1
                )
        WHERE ((SELECT COUNT(*) FROM foldertable) < {$maxFolderCount})
        ";

什么問題

1. 現在文件夾 ID 是唯一的,但不是隨機的。 2. 我的想法是說它會產生性能問題。

我不能做什么

  1. 無法將folderid設置為唯一。

另一個想法如果我想要一個 6 字符的字符串。 ,我該怎么做?

方案A——Hash:

使用散列 function 創建一個新號碼。 這取決於已經具有AUTO_INCREMENT id的表:

SELECT MD5(MAX(id)) FROM t

優點:簡單、快速

缺點:需要id ,“數字”實際上是一個 32 字符的十六進制字符串。

B計划——預建清單:

  1. 建立了一個數字 100..50000 的表nums

  2. 將它們洗牌到不同的表中:

     CREATE TABLE rand_nums SELECT num FROM nums ORDER BY RAND();
  3. 提取一個數字

     SELECT num FROM rand_nums LIMIT 1; -- get DELETE FROM rand_nums WHERE num =...; -- remove

優點:高效(在 setup_

缺點:需要更多復雜性來處理步驟 3 中數字和效率的並發獲取

計划 C -- 其他想法

如果您后退一步,您可能會發現更高級別的目標可以用其他一些技術代替。 而且您可能需要“獲取隨機行”作為原語。 如果是這樣,這里有一些“相當不錯”的技術: http://mysql.rjweb.org/doc.php/random

關於:

另一個想法如果我想要一個 6 字符的字符串。 ,我該怎么做?

select concat(
    cast(char(64+floor(rand()*26+1)) as char),
    cast(char(64+floor(rand()*26+1)) as char),
    cast(char(64+floor(rand()*26+1)) as char),
    cast(char(64+floor(rand()*26+1)) as char),
    cast(char(64+floor(rand()*26+1)) as char),
    cast(char(64+floor(rand()*26+1)) as char)) as char6;

或者,如果您想要更長的語句:

with recursive cte as ( 
   select 'A' as a
   union all 
   select CHAR(ORD(a)+1)
   from cte
   where a<'Z') 
select concat(c1.a,c2.a,c3.a,c4.a,c5.a,c6.a) as char6
from cte c1
cross join (select a from cte order by rand()*26+1 limit 1) c2
cross join (select a from cte order by rand()*26+1 limit 1) c3
cross join (select a from cte order by rand()*26+1 limit 1) c4
cross join (select a from cte order by rand()*26+1 limit 1) c5
cross join (select a from cte order by rand()*26+1 limit 1) c6
order by rand()*26+1
limit 1;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM