Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Thực hiện một lúc / vòng lặp để nhận được 10 kết quả ngẫu nhiên

Vui lòng ngừng sử dụng ORDER BY RAND() . Chỉ dừng lại. Thao tác này có độ phức tạp là n*log2(n) , có nghĩa là thời gian dành cho truy vấn sẽ tăng lên "

Các mục nhập
    entries  |  time units
  -------------------------
         10  |         1     /* if this takes 0.001s */
      1'000  |       300
  1'000'000  |   600'000     /* then this will need 10 minutes */

Nếu bạn muốn tạo các kết quả ngẫu nhiên, hãy tạo một thủ tục được lưu trữ để tạo ra chúng. Một cái gì đó như thế này (mã được lấy từ bài viết này , mà bạn nên đọc):

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 ;

Và để sử dụng nó, bạn sẽ viết:

CALL get_rands(10);
SELECT * FROM rands;

Đối với việc thực thi tất cả trên PHP, bạn nên ngừng sử dụng mysql_* cổ API. Nó đã hơn 10 năm tuổi và không còn được duy trì. Cộng đồng thậm chí đã bắt đầu quá trình vì không dùng chúng nữa. Không nên có thêm bất kỳ mã mới nào được viết bằng mysql_* vào năm 2012. Thay vào đó, bạn nên sử dụng PDO hoặc MySQLi . Về cách viết nó (với 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);
}

Cập nhật

Nếu yêu cầu là nhận được không chỉ 10 kết quả ngẫu nhiên, mà thực sự là 10 kết quả ngẫu nhiên DUY NHẤT , thì nó sẽ yêu cầu hai thay đổi đối với PROCEDURE :

  1. Bảng tạm thời phải thực thi tính duy nhất của các mục nhập:

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

    Nó cũng có thể có ý nghĩa khi chỉ thu thập các ID chứ không phải các giá trị. Đặc biệt nếu những gì bạn đang tìm kiếm là 10 bài báo độc đáo, không chỉ các thẻ.

  2. Khi phát hiện thấy việc chèn một giá trị trùng lặp, cnt bộ đếm không được giảm. Điều này có thể được đảm bảo bằng cách thêm HANDLER (trước định nghĩa của LOOP ), sẽ "bắt" cảnh báo đã nêu và điều chỉnh bộ đếm:

    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. Sử dụng tệp .php để tạo kết xuất MySQL

  2. CONV () - Chuyển đổi số giữa các cơ sở khác nhau trong MySQL

  3. PostgreSQL và MySQL, một so sánh

  4. Sử dụng trình kích hoạt để dừng chèn hoặc cập nhật

  5. Tạo sơ đồ cơ sở dữ liệu trong MySQL Workbench