今天我們要實現從隨機抽取一條數據庫記錄的功能,並且抽取出來的數據記錄不能重復;
1、首先我們看文章表中的數據:

2、實現功能代碼如下:
1 /** 2 * 獲取隨機的N篇文篇 3 * @param int $len 文章篇數 4 */ 5 public static function getRandom($len = 6) { 6 # 查詢數據庫,得到最小Id 7 # SELECT min(id) FROM mimi_aritcle 8 $min = Db::name(self::$tb)->field('min(id)')->select(); 9 $min = $min[0]['min(id)']; 10 11 # 查詢數據庫,得到最大id 12 # SELECT max(id) FROM mimi_article 13 $max = Db::name(self::$tb)->field('max(id)')->select(); 14 $max = $max[0]['max(id)']; 15 16 # 初始化存儲數據 17 $result = []; 18 # 初始化id數組 19 $randId_arr = []; 20 21 for ($i = 1; $i <= $len; $i++) { 22 # 先設重復提取記錄為false,進入do循環 23 $is_repeat_2 = false; 24 25 # do..while,即使條件不成立,循環起碼執行一次 26 do { 27 do { 28 # 產生一個隨機整數 29 # 注意:產生的整數與數據庫無關,不要因為兩個參數是從數據庫中得到的, 30 # 就誤以為是在產生數據庫中的隨機id 31 $randId = rand($min, $max); 32 33 # 判斷是否有重復提取的記錄 34 $is_repeat = in_array($randId, $randId_arr); 35 } while ($is_repeat); 36 37 if($is_repeat_2){ 38 # 將提取出的不同id進行入棧 39 array_push($randId_arr, $row[0]['id']); 40 } 41 42 # 抽取一條數據庫記錄 43 /** 44 * 首先,我們要記住: 45 * 步驟一表圖中查詢數據庫,獲取到最小id是1, 最大id是50,就能知道數據庫中一定有id=1和id=50的記錄 46 * 所以, 47 * 1、這里使用id>$randId而不是id=$randId,是防止數據庫中的某條記錄被刪除,導致找不到數據庫中對應的id記錄; 48 * 例子: 49 * (1) 如果隨機抽取的$randId為6,那么使用條件id>$randId-1的話,就會讀取到數據庫中所有id>5的記錄; 50 * 從數據庫截圖中,我們可以看到,能夠讀取到數據庫id=10、20、30、40、50的記錄 51 * (2) 如果我們使用id=$randId,隨機抽取的$randId為6,那么使用功能id=$randId的話,就會讀取到數據庫中id=6的固定記錄, 52 * 但是數據庫中沒有id=6的記錄,就會發生錯誤 53 * 54 * 2、這里使用id>$randId-1而不是id>$randId,是為了防止我們隨機抽取的數為最大數50的時候,條件不成立, 55 * 從而導致報錯,因為id=50是數據庫中最大數了 56 * 例如: 57 * (1) 如果隨機抽取的$randId為最大數50,那么使用條件id>$randId-1的話,就會讀取到數據庫中所有id>49的記錄, 58 * 由於符合id>49條件的只有id=50的記錄,那么就能保證,我有數據可以提取到; 59 * (2) 如果隨機抽取的$randId為最大數50,那么使用條件id>$randId的話,就會讀取到數據庫中所有id>50的記錄, 60 * 但是數據庫中沒有符合條件的數據,就會發生錯誤 61 * (3) 如果隨機抽取的$randId為最小數1,使用條件 id>$randId 的話,id = 1 的記錄永遠也不能被隨機選中 62 * 63 * 3、這里使用order('id ASC')而不是order('id DESC')原因:當我們獲取到數據后,要獲取最接近$randId的值 64 * (1) 如果隨機抽取的$randId為6,我們就能從所有id>5的記錄,即id=10、20、30、40、50 65 * 的記錄,這時候的結果是循環6次后的總體列表,那我們需要最靠近6的記錄,就需要使用order('id ASC') 66 * 進行升序排列,這時候,列表中的第一個數據就是id=10的,就是我們想要的記錄 67 * (2) 如果隨機抽取的$randId為6,我們就能從所有id>5的記錄,即id=10、20、30、40、50 68 * 的記錄,如果使用order('id DESC'),那么我們得到的數據永遠是最不靠近6的記錄,即id=50的記錄 69 * (3) 不使用order,有時候會排列不一樣,(通常在數據記錄不同時才會發現到) 70 * 71 * 4、這里使用limit原因:因為我們需要的是一條記錄,而不是一個列表,所以,我們只需要提取符合條件的第一條記錄即可 72 * 例子: 73 * (1) 如果隨機抽取的$randId為6,那么使用條件id>$randId-1的話,就會讀取到數據庫中所有id>5的記錄而不是固定一條記錄; 74 * 從數據庫截圖中,我們可以看到,能夠讀取到數據庫id=10、20、30、40、50的記錄,但是我們循環一次只需要一條記錄,那么 75 * 只需要提取第一條符合的記錄,就是id=10的記錄 76 * (2) 如果我們不使用limit的話,那么系統就會把所有符合條件的記錄都提取出來 77 * 78 */ 79 $row = Db::name(self::$tb) 80 ->field('id, title, href') 81 ->where(['id' => ['>', $randId - 1]]) 82 ->order('id ASC') 83 ->limit(0, 1) 84 ->select(); 85 86 # 判斷是否有重復提取的數據庫記錄 87 $is_repeat_2 = in_array($row[0]['id'], $randId_arr); 88 } while ($is_repeat_2); 89 90 91 # 將提取出來的數據庫id進行入棧 92 array_push($randId_arr, $row[0]['id']); 93 94 if(empty($row)){ 95 return false; 96 } 97 98 # 將提取出的所有最終數據庫數據入棧 99 array_push($result, $row[0]); 100 } 101 102 return $result; 103 }
以上
加油ヾ(◍°∇°◍)ノ゙
