Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Lakukan while/loop untuk mendapatkan 10 hasil random

Tolong, berhenti menggunakan ORDER BY RAND() . Berhenti saja. Operasi ini memiliki kompleksitas n*log2(n) , yang berarti bahwa waktu yang dihabiskan untuk kueri akan bertambah "

    entries  |  time units
  -------------------------
         10  |         1     /* if this takes 0.001s */
      1'000  |       300
  1'000'000  |   600'000     /* then this will need 10 minutes */

Jika Anda ingin menghasilkan hasil acak, buat prosedur tersimpan, yang menghasilkannya. Kira-kira seperti ini (kode diambil dari artikel ini , yang harus Anda baca):

DELIMITER $$
DROP PROCEDURE IF EXISTS get_rands$$
CREATE PROCEDURE get_rands(IN cnt INT)
BEGIN
  DROP TEMPORARY TABLE IF EXISTS rands;
  CREATE TEMPORARY TABLE rands ( tagname VARCHAR(63) );

loop_me: LOOP
    IF cnt < 1 THEN
      LEAVE loop_me;
    END IF;

    SET cnt = cnt - 1;

    INSERT INTO rands
       SELECT tags.tagname
         FROM tags 
         JOIN (SELECT (RAND()*(SELECT MAX(tags.id) FROM tags)) AS id) AS choices
        WHERE tags.id >= choices.id
        LIMIT 1;

  END LOOP loop_me;
END$$
DELIMITER ;

Dan untuk menggunakannya, Anda akan menulis:

CALL get_rands(10);
SELECT * FROM rands;

Adapun untuk menjalankan semuanya di sisi PHP, Anda harus berhenti menggunakan mysql_* kuno API. Sudah lebih dari 10 tahun dan tidak terawat lagi. Komunitas bahkan memulai proses untuk mencela mereka. Seharusnya tidak ada lagi kode baru yang ditulis dengan mysql_* pada tahun 2012. Sebagai gantinya, Anda harus menggunakan PDO atau MySQLi . Adapun cara penulisannya (dengan PDO):

// creates DB connection
$connection = new PDO('mysql:host=localhost;dbname=mydb;charset=UTF-8', 
                      'username', 'password');
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

// executes the procedure and creates select statement
$connection->exec('CALL get_rands(10)');
$statement = $connection->query('SELECT * FROM rands');

// performs query and collects all the info
if ($statement->execute())
{
    $tags = $statement->fetchAll(PDO::FETCH::ASSOC);
}

Perbarui

Jika persyaratannya adalah untuk mendapatkan tidak hanya 10 hasil acak, tetapi sebenarnya 10 hasil acak UNIK , maka diperlukan dua perubahan pada PROCEDURE :

  1. Tabel sementara harus menerapkan keunikan entri:

    CREATE TEMPORARY TABLE rands ( tagname VARCHAR(63) UNIQUE);
    

    Mungkin juga masuk akal untuk mengumpulkan ID saja dan bukan nilainya. Apalagi jika yang Anda cari adalah 10 artikel unik, bukan sekedar tag.

  2. Saat memasukkan nilai duplikat ditemukan, cnt counter tidak boleh berkurang. Hal ini dapat dipastikan dengan menambahkan HANDLER (sebelum definisi LOOP ), yang akan "menangkap" peringatan yang muncul, dan menyesuaikan penghitung:

    DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET cnt = cnt + 1;
    


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Menggunakan Kata Sandi Asli Dengan MySQL 5.7

  2. Bagaimana cara mengekspor database SQL Server ke MySQL?

  3. Jumlah total kunci melebihi ukuran meja kunci

  4. Peringatan:mysqli_query() mengharapkan parameter 1 menjadi mysqli, sumber daya diberikan

  5. Bagaimana cara saya menanyakan antara dua tanggal menggunakan MySQL?